[svn-commits] rmudgett: branch rmudgett/subaddr_xfer r2157 - /team/rmudgett/subaddr_xfer/
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Tue Dec 7 17:19:40 CST 2010
Author: rmudgett
Date: Tue Dec 7 17:19:33 2010
New Revision: 2157
URL: http://svnview.digium.com/svn/libpri?view=rev&rev=2157
Log:
Send connected line subaddress updates.
Modified:
team/rmudgett/subaddr_xfer/pri.c
team/rmudgett/subaddr_xfer/pri_facility.c
team/rmudgett/subaddr_xfer/pri_facility.h
team/rmudgett/subaddr_xfer/pri_internal.h
team/rmudgett/subaddr_xfer/q931.c
Modified: team/rmudgett/subaddr_xfer/pri.c
URL: http://svnview.digium.com/svn/libpri/team/rmudgett/subaddr_xfer/pri.c?view=diff&rev=2157&r1=2156&r2=2157
==============================================================================
--- team/rmudgett/subaddr_xfer/pri.c (original)
+++ team/rmudgett/subaddr_xfer/pri.c Tue Dec 7 17:19:33 2010
@@ -949,6 +949,9 @@
{
struct q931_party_id party_id;
unsigned idx;
+ unsigned new_name;
+ unsigned new_number;
+ unsigned new_subaddress;
struct q931_call *subcall;
if (!ctrl || !pri_is_call_valid(ctrl, call)) {
@@ -957,13 +960,14 @@
pri_copy_party_id_to_q931(&party_id, &connected->id);
q931_party_id_fixup(ctrl, &party_id);
- if (!q931_party_id_cmp(&party_id, &call->local_id)) {
- /* The local party information did not change so do nothing. */
- return 0;
- }
+
+ new_name = q931_party_name_cmp(&party_id.name, &call->local_id.name);
+ new_number = q931_party_number_cmp(&party_id.number, &call->local_id.number);
+ new_subaddress = party_id.subaddress.valid
+ && q931_party_subaddress_cmp(&party_id.subaddress, &call->local_id.subaddress);
+
+ /* Update the call and all subcalls with new local_id. */
call->local_id = party_id;
-
- /* Update all subcalls with new local_id. */
if (call->outboundbroadcast && call->master_call == call) {
for (idx = 0; idx < ARRAY_LEN(call->subcalls); ++idx) {
subcall = call->subcalls[idx];
@@ -982,23 +986,90 @@
* The local party transferred to someone else before
* the remote end answered.
*/
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_EUROISDN_E1:
+ case PRI_SWITCH_EUROISDN_T1:
+ if (BRI_NT_PTMP(ctrl)) {
+ /*
+ * NT PTMP mode
+ *
+ * We should not send these messages to the network if we are
+ * the CPE side since phones do not transfer calls within
+ * themselves. Well... If you consider handing the handset to
+ * someone else a transfer then how is the network to know?
+ */
+ if (new_number) {
+ q931_notify_redirection(ctrl, call, PRI_NOTIFY_TRANSFER_ACTIVE,
+ &party_id.number);
+ }
+ if (new_subaddress || (party_id.subaddress.valid && new_number)) {
+ q931_subaddress_transfer(ctrl, call);
+ }
+ } else if (PTP_MODE(ctrl)) {
+ /* PTP mode */
+ if (new_number) {
+ /* Immediately send EctInform APDU, callStatus=answered(0) */
+ send_call_transfer_complete(ctrl, call, 0);
+ }
+ if (new_subaddress || (party_id.subaddress.valid && new_number)) {
+ q931_subaddress_transfer(ctrl, call);
+ }
+ }
+ break;
+ case PRI_SWITCH_QSIG:
+ if (new_name || new_number) {
+ /* Immediately send CallTransferComplete APDU, callStatus=answered(0) */
+ send_call_transfer_complete(ctrl, call, 0);
+ }
+ if (new_subaddress
+ || (party_id.subaddress.valid && (new_name || new_number))) {
+ q931_subaddress_transfer(ctrl, call);
+ }
+ break;
+ default:
+ break;
+ }
+ break;
case Q931_CALL_STATE_ACTIVE:
switch (ctrl->switchtype) {
case PRI_SWITCH_EUROISDN_E1:
case PRI_SWITCH_EUROISDN_T1:
- if (PTMP_MODE(ctrl)) {
- /* PTMP mode */
- q931_notify_redirection(ctrl, call, PRI_NOTIFY_TRANSFER_ACTIVE,
- &call->local_id.number);
- } else {
+ if (BRI_NT_PTMP(ctrl)) {
+ /*
+ * NT PTMP mode
+ *
+ * We should not send these messages to the network if we are
+ * the CPE side since phones do not transfer calls within
+ * themselves. Well... If you consider handing the handset to
+ * someone else a transfer then how is the network to know?
+ */
+ if (new_number) {
+ q931_request_subaddress(ctrl, call, PRI_NOTIFY_TRANSFER_ACTIVE,
+ &party_id.number);
+ }
+ if (new_subaddress || (party_id.subaddress.valid && new_number)) {
+ q931_subaddress_transfer(ctrl, call);
+ }
+ } else if (PTP_MODE(ctrl)) {
/* PTP mode */
- /* Immediately send EctInform APDU, callStatus=answered(0) */
- send_call_transfer_complete(ctrl, call, 0);
+ if (new_number) {
+ /* Immediately send EctInform APDU, callStatus=answered(0) */
+ send_call_transfer_complete(ctrl, call, 0);
+ }
+ if (new_subaddress || (party_id.subaddress.valid && new_number)) {
+ q931_subaddress_transfer(ctrl, call);
+ }
}
break;
case PRI_SWITCH_QSIG:
- /* Immediately send CallTransferComplete APDU, callStatus=answered(0) */
- send_call_transfer_complete(ctrl, call, 0);
+ if (new_name || new_number) {
+ /* Immediately send CallTransferComplete APDU, callStatus=answered(0) */
+ send_call_transfer_complete(ctrl, call, 0);
+ }
+ if (new_subaddress
+ || (party_id.subaddress.valid && (new_name || new_number))) {
+ q931_subaddress_transfer(ctrl, call);
+ }
break;
default:
break;
Modified: team/rmudgett/subaddr_xfer/pri_facility.c
URL: http://svnview.digium.com/svn/libpri/team/rmudgett/subaddr_xfer/pri_facility.c?view=diff&rev=2157&r1=2156&r2=2157
==============================================================================
--- team/rmudgett/subaddr_xfer/pri_facility.c (original)
+++ team/rmudgett/subaddr_xfer/pri_facility.c Tue Dec 7 17:19:33 2010
@@ -3359,6 +3359,204 @@
|| q931_facility(ctrl, call)) {
pri_message(ctrl,
"Could not schedule facility message for call transfer completed.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*!
+ * \internal
+ * \brief Encode the ETSI RequestSubaddress invoke message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param pos Starting position to encode the facility ie contents.
+ * \param end End of facility ie contents encoding data buffer.
+ *
+ * \retval Start of the next ASN.1 component to encode on success.
+ * \retval NULL on error.
+ */
+static unsigned char *enc_etsi_request_subaddress(struct pri *ctrl, unsigned char *pos,
+ unsigned char *end)
+{
+ struct rose_msg_invoke msg;
+
+ pos = facility_encode_header(ctrl, pos, end, NULL);
+ if (!pos) {
+ return NULL;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ msg.operation = ROSE_ETSI_RequestSubaddress;
+ msg.invoke_id = get_invokeid(ctrl);
+
+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
+
+ return pos;
+}
+
+/*!
+ * \brief Encode and queue the RequestSubaddress invoke message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param call Call leg from which to encode message.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int rose_request_subaddress_encode(struct pri *ctrl, struct q931_call *call)
+{
+ unsigned char buffer[256];
+ unsigned char *end;
+
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_EUROISDN_E1:
+ case PRI_SWITCH_EUROISDN_T1:
+ end = enc_etsi_request_subaddress(ctrl, buffer, buffer + sizeof(buffer));
+ break;
+ case PRI_SWITCH_QSIG:
+ default:
+ return -1;
+ }
+ if (!end) {
+ return -1;
+ }
+
+ return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
+}
+
+/*!
+ * \internal
+ * \brief Encode the ETSI SubaddressTransfer invoke message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param pos Starting position to encode the facility ie contents.
+ * \param end End of facility ie contents encoding data buffer.
+ * \param call Call leg from which to encode message.
+ *
+ * \retval Start of the next ASN.1 component to encode on success.
+ * \retval NULL on error.
+ */
+static unsigned char *enc_etsi_subaddress_transfer(struct pri *ctrl, unsigned char *pos,
+ unsigned char *end, struct q931_call *call)
+{
+ struct rose_msg_invoke msg;
+
+ pos = facility_encode_header(ctrl, pos, end, NULL);
+ if (!pos) {
+ return NULL;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ msg.operation = ROSE_ETSI_SubaddressTransfer;
+ msg.invoke_id = get_invokeid(ctrl);
+
+ if (!call->local_id.subaddress.valid) {
+ return NULL;
+ }
+ q931_copy_subaddress_to_rose(ctrl, &msg.args.etsi.SubaddressTransfer.subaddress,
+ &call->local_id.subaddress);
+
+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
+
+ return pos;
+}
+
+/*!
+ * \internal
+ * \brief Encode the Q.SIG SubaddressTransfer invoke message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param pos Starting position to encode the facility ie contents.
+ * \param end End of facility ie contents encoding data buffer.
+ * \param call Call leg from which to encode message.
+ *
+ * \retval Start of the next ASN.1 component to encode on success.
+ * \retval NULL on error.
+ */
+static unsigned char *enc_qsig_subaddress_transfer(struct pri *ctrl,
+ unsigned char *pos, unsigned char *end, struct q931_call *call)
+{
+ struct fac_extension_header header;
+ struct rose_msg_invoke msg;
+
+ memset(&header, 0, sizeof(header));
+ header.nfe_present = 1;
+ header.nfe.source_entity = 0; /* endPINX */
+ header.nfe.destination_entity = 0; /* endPINX */
+ header.interpretation_present = 1;
+ header.interpretation = 0; /* discardAnyUnrecognisedInvokePdu */
+ pos = facility_encode_header(ctrl, pos, end, &header);
+ if (!pos) {
+ return NULL;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ msg.operation = ROSE_QSIG_SubaddressTransfer;
+ msg.invoke_id = get_invokeid(ctrl);
+
+ if (!call->local_id.subaddress.valid) {
+ return NULL;
+ }
+ q931_copy_subaddress_to_rose(ctrl,
+ &msg.args.qsig.SubaddressTransfer.redirection_subaddress,
+ &call->local_id.subaddress);
+
+ pos = rose_encode_invoke(ctrl, pos, end, &msg);
+
+ return pos;
+}
+
+/*!
+ * \internal
+ * \brief Encode and queue the SubaddressTransfer invoke message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param call Call leg from which to encode message.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int rose_subaddress_transfer_encode(struct pri *ctrl, struct q931_call *call)
+{
+ unsigned char buffer[256];
+ unsigned char *end;
+
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_EUROISDN_E1:
+ case PRI_SWITCH_EUROISDN_T1:
+ end =
+ enc_etsi_subaddress_transfer(ctrl, buffer, buffer + sizeof(buffer), call);
+ break;
+ case PRI_SWITCH_QSIG:
+ end =
+ enc_qsig_subaddress_transfer(ctrl, buffer, buffer + sizeof(buffer), call);
+ break;
+ default:
+ return -1;
+ }
+ if (!end) {
+ return -1;
+ }
+
+ return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
+}
+
+/*!
+ * \brief Send a FACILITY SubaddressTransfer.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int send_subaddress_transfer(struct pri *ctrl, struct q931_call *call)
+{
+ if (rose_subaddress_transfer_encode(ctrl, call)
+ || q931_facility(ctrl, call)) {
+ pri_message(ctrl,
+ "Could not schedule facility message for subaddress transfer.\n");
return -1;
}
Modified: team/rmudgett/subaddr_xfer/pri_facility.h
URL: http://svnview.digium.com/svn/libpri/team/rmudgett/subaddr_xfer/pri_facility.h?view=diff&rev=2157&r1=2156&r2=2157
==============================================================================
--- team/rmudgett/subaddr_xfer/pri_facility.h (original)
+++ team/rmudgett/subaddr_xfer/pri_facility.h Tue Dec 7 17:19:33 2010
@@ -221,6 +221,8 @@
int send_reroute_request(struct pri *ctrl, q931_call *call, const struct q931_party_id *caller, const struct q931_party_redirecting *deflection, int subscription_option);
int send_call_transfer_complete(struct pri *pri, q931_call *call, int call_status);
+int rose_request_subaddress_encode(struct pri *ctrl, struct q931_call *call);
+int send_subaddress_transfer(struct pri *ctrl, struct q931_call *call);
int rose_diverting_leg_information1_encode(struct pri *pri, q931_call *call);
int rose_diverting_leg_information3_encode(struct pri *pri, q931_call *call, int messagetype);
Modified: team/rmudgett/subaddr_xfer/pri_internal.h
URL: http://svnview.digium.com/svn/libpri/team/rmudgett/subaddr_xfer/pri_internal.h?view=diff&rev=2157&r1=2156&r2=2157
==============================================================================
--- team/rmudgett/subaddr_xfer/pri_internal.h (original)
+++ team/rmudgett/subaddr_xfer/pri_internal.h Tue Dec 7 17:19:33 2010
@@ -950,6 +950,8 @@
struct q931_call *q931_find_link_id_call(struct pri *ctrl, int link_id);
struct q931_call *q931_find_held_active_call(struct pri *ctrl, struct q931_call *held_call);
+int q931_request_subaddress(struct pri *ctrl, struct q931_call *call, int notify, const struct q931_party_number *number);
+int q931_subaddress_transfer(struct pri *ctrl, struct q931_call *call);
int q931_notify_redirection(struct pri *ctrl, q931_call *call, int notify, const struct q931_party_number *number);
struct pri_cc_record *pri_cc_find_by_reference(struct pri *ctrl, unsigned reference_id);
Modified: team/rmudgett/subaddr_xfer/q931.c
URL: http://svnview.digium.com/svn/libpri/team/rmudgett/subaddr_xfer/q931.c?view=diff&rev=2157&r1=2156&r2=2157
==============================================================================
--- team/rmudgett/subaddr_xfer/q931.c (original)
+++ team/rmudgett/subaddr_xfer/q931.c Tue Dec 7 17:19:33 2010
@@ -933,6 +933,31 @@
}
return number_value | number_screening;
+}
+
+/*!
+ * \brief Find the winning subcall if it exists or current call if not outboundbroadcast.
+ *
+ * \param call Starting Q.931 call record of search.
+ *
+ * \retval winning-call or given call if not outboundbroadcast.
+ * \retval NULL if no winning call yet.
+ */
+struct q931_call *q931_find_winning_call(struct q931_call *call)
+{
+ struct q931_call *master;
+
+ master = call->master_call;
+ if (master->outboundbroadcast) {
+ /* We have potential subcalls. Now get the winning call if declared yet. */
+ if (master->pri_winner < 0) {
+ /* Winner not declared yet.*/
+ call = NULL;
+ } else {
+ call = master->subcalls[master->pri_winner];
+ }
+ }
+ return call;
}
/*!
@@ -4733,6 +4758,88 @@
return send_message(ctrl, c, Q931_FACILITY, facility_ies);
}
+static int facility_notify_ies[] = {
+ Q931_IE_FACILITY,
+ Q931_IE_NOTIFY_IND,
+ Q931_IE_REDIRECTION_NUMBER,
+ -1
+};
+
+/*!
+ * \brief Send a FACILITY RequestSubaddress with optional redirection number.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg
+ * \param notify Notification indicator
+ * \param number Redirection number to send if not NULL.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int q931_request_subaddress(struct pri *ctrl, struct q931_call *call, int notify, const struct q931_party_number *number)
+{
+ struct q931_call *winner;
+
+ winner = q931_find_winning_call(call);
+ if (!winner) {
+ return -1;
+ }
+ if (number) {
+ winner->redirection_number = *number;
+ } else {
+ q931_party_number_init(&winner->redirection_number);
+ }
+ winner->notify = notify;
+ if (rose_request_subaddress_encode(ctrl, winner)
+ || send_message(ctrl, winner, Q931_FACILITY, facility_notify_ies)) {
+ pri_message(ctrl,
+ "Could not schedule facility message for request subaddress.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*!
+ * \brief Send a FACILITY SubaddressTransfer to all parties.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int q931_subaddress_transfer(struct pri *ctrl, struct q931_call *call)
+{
+ int status;
+ unsigned idx;
+ struct q931_call *subcall;
+
+ if (call->outboundbroadcast && call->master_call == call) {
+ status = 0;
+ for (idx = 0; idx < ARRAY_LEN(call->subcalls); ++idx) {
+ subcall = call->subcalls[idx];
+ if (subcall) {
+ /* Send to all subcalls that have given a positive response. */
+ switch (subcall->ourcallstate) {
+ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
+ case Q931_CALL_STATE_CALL_DELIVERED:
+ case Q931_CALL_STATE_ACTIVE:
+ if (send_subaddress_transfer(ctrl, subcall)) {
+ status = -1;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ } else {
+ status = send_subaddress_transfer(ctrl, call);
+ }
+ return status;
+}
+
static int notify_ies[] = { Q931_IE_NOTIFY_IND, Q931_IE_REDIRECTION_NUMBER, -1 };
/*!
@@ -5485,31 +5592,6 @@
/* release the structure */
res += pri_hangup(ctrl, c, cause);
return res;
-}
-
-/*!
- * \brief Find the winning subcall if it exists or current call if not outboundbroadcast.
- *
- * \param call Starting Q.931 call record of search.
- *
- * \retval winning-call or given call if not outboundbroadcast.
- * \retval NULL if no winning call yet.
- */
-struct q931_call *q931_find_winning_call(struct q931_call *call)
-{
- struct q931_call *master;
-
- master = call->master_call;
- if (master->outboundbroadcast) {
- /* We have potential subcalls. Now get the winning call if declared yet. */
- if (master->pri_winner < 0) {
- /* Winner not declared yet.*/
- call = NULL;
- } else {
- call = master->subcalls[master->pri_winner];
- }
- }
- return call;
}
static int connect_ack_ies[] = { -1 };
More information about the svn-commits
mailing list