[libpri-commits] rmudgett: branch 1.4 r2190 - /branches/1.4/
SVN commits to the libpri project
libpri-commits at lists.digium.com
Fri Feb 4 13:59:50 CST 2011
Author: rmudgett
Date: Fri Feb 4 13:59:45 2011
New Revision: 2190
URL: http://svnview.digium.com/svn/libpri?view=rev&rev=2190
Log:
Add display ie text handling options.
The display ie handling can be controlled independently in the send and
receive directions with the following options:
* Block display text data.
* Use display text in SETUP/CONNECT messages for name.
* Use display text for COLP name updates (FACILITY/NOTIFY as appropriate).
* Pass arbitrary display text during a call. Sent in INFORMATION
messages. Received from any message that the display text was not used as
a name.
If the display options are not set then the options default to legacy
behavior.
Modified:
branches/1.4/libpri.h
branches/1.4/pri.c
branches/1.4/pri_facility.c
branches/1.4/pri_internal.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=2190&r1=2189&r2=2190
==============================================================================
--- branches/1.4/libpri.h (original)
+++ branches/1.4/libpri.h Fri Feb 4 13:59:45 2011
@@ -547,6 +547,7 @@
#define PRI_SUBCMD_AOC_CHARGING_REQ_RSP 22 /*!< Advice Of Charge Request Response information */
#define PRI_SUBCMD_MCID_REQ 23 /*!< Malicious Call ID Request */
#define PRI_SUBCMD_MCID_RSP 24 /*!< Malicious Call ID Request response */
+#define PRI_SUBCMD_DISPLAY_TEXT 25 /*!< Received display ie text */
#if defined(STATUS_REQUEST_PLACE_HOLDER)
struct pri_subcmd_status_request {
@@ -965,6 +966,35 @@
* \note Use pri_facility_reject2str() to convert the reject_code.
*/
int fail_code;
+};
+
+struct pri_subcmd_display_txt {
+ /*!
+ * \brief Character set the text is using.
+ * \details
+ * unknown(0),
+ * iso8859-1(1),
+ * enum-value-withdrawn-by-ITU-T(2)
+ * iso8859-2(3),
+ * iso8859-3(4),
+ * iso8859-4(5),
+ * iso8859-5(6),
+ * iso8859-7(7),
+ * iso10646-BmpString(8),
+ * iso10646-utf-8String(9)
+ */
+ int char_set;
+ /*!
+ * \brief Number of octets in the display message.
+ * \note Not including any added null terminator.
+ */
+ int length;
+ /*!
+ * \brief Display text data.
+ * \note Null terminated on receive.
+ * \note Does not need to be null terminated on send.
+ */
+ char text[128];
};
struct pri_subcommand {
@@ -999,6 +1029,7 @@
struct pri_subcmd_aoc_e aoc_e;
struct pri_subcmd_mcid_req mcid_req;
struct pri_subcmd_mcid_rsp mcid_rsp;
+ struct pri_subcmd_display_txt display;
} u;
};
@@ -1840,6 +1871,55 @@
*/
void pri_aoc_events_enable(struct pri *ctrl, int enable);
+#define PRI_DISPLAY_OPTION_BLOCK (1 << 0) /*!< Do not pass display text. */
+#define PRI_DISPLAY_OPTION_NAME_INITIAL (1 << 1) /*!< Use display in SETUP/CONNECT for name. */
+#define PRI_DISPLAY_OPTION_NAME_UPDATE (1 << 2) /*!< Use display in FACILITY/NOTIFY for COLP name if appropriate. */
+#define PRI_DISPLAY_OPTION_TEXT (1 << 3) /*!< Pass arbitrary display text in INFORMATION messages during call. */
+
+/*!
+ * \brief Set the display ie send policy options.
+ *
+ * \param ctrl D channel controller.
+ * \param flags Option flags to apply.
+ *
+ * \note
+ * If no flags set then legacy default behaviour.
+ *
+ * \note
+ * Not all options are supported by all switches.
+ *
+ * \return Nothing
+ */
+void pri_display_options_send(struct pri *ctrl, unsigned long flags);
+
+/*!
+ * \brief Set the display ie receive policy options.
+ *
+ * \param ctrl D channel controller.
+ * \param flags Option flags to apply.
+ *
+ * \note
+ * If no flags set then legacy default behaviour.
+ *
+ * \note
+ * Not all options are supported by all switches.
+ *
+ * \return Nothing
+ */
+void pri_display_options_receive(struct pri *ctrl, unsigned long flags);
+
+/*!
+ * \brief Send display text during a call.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg
+ * \param display Display text to send.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int pri_display_text(struct pri *ctrl, q931_call *call, const struct pri_subcmd_display_txt *display);
+
/*!
* \brief Set the call hold feature enable flag.
*
Modified: branches/1.4/pri.c
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri.c?view=diff&rev=2190&r1=2189&r2=2190
==============================================================================
--- branches/1.4/pri.c (original)
+++ branches/1.4/pri.c Fri Feb 4 13:59:45 2011
@@ -289,6 +289,60 @@
}
/*!
+ * \internal
+ * \brief Determine the default display text send options.
+ *
+ * \param ctrl D channel controller.
+ *
+ * \return Default display text send options. (legacy behaviour defaults)
+ */
+static unsigned long pri_display_options_send_default(struct pri *ctrl)
+{
+ unsigned long flags;
+
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_QSIG:
+ flags = PRI_DISPLAY_OPTION_BLOCK;
+ break;
+ case PRI_SWITCH_EUROISDN_E1:
+ case PRI_SWITCH_EUROISDN_T1:
+ if (ctrl->localtype == PRI_CPE) {
+ flags = PRI_DISPLAY_OPTION_BLOCK;
+ break;
+ }
+ flags = PRI_DISPLAY_OPTION_NAME_INITIAL;
+ break;
+ default:
+ flags = PRI_DISPLAY_OPTION_NAME_INITIAL;
+ break;
+ }
+ return flags;
+}
+
+/*!
+ * \internal
+ * \brief Determine the default display text receive options.
+ *
+ * \param ctrl D channel controller.
+ *
+ * \return Default display text receive options. (legacy behaviour defaults)
+ */
+static unsigned long pri_display_options_receive_default(struct pri *ctrl)
+{
+ unsigned long flags;
+
+ switch (ctrl->switchtype) {
+ case PRI_SWITCH_QSIG:
+ flags = PRI_DISPLAY_OPTION_BLOCK;
+ break;
+ default:
+ flags = PRI_DISPLAY_OPTION_NAME_INITIAL;
+ break;
+ }
+ return flags;
+}
+
+/*!
* \brief Destroy the given link.
*
* \param link Q.921 link to destroy.
@@ -481,6 +535,8 @@
ctrl->q931_rxcount = 0;
ctrl->q931_txcount = 0;
+ ctrl->display_flags.send = pri_display_options_send_default(ctrl);
+ ctrl->display_flags.receive = pri_display_options_receive_default(ctrl);
switch (switchtype) {
case PRI_SWITCH_GR303_EOC:
ctrl->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
@@ -999,7 +1055,7 @@
*/
if (new_number) {
q931_notify_redirection(ctrl, call, PRI_NOTIFY_TRANSFER_ACTIVE,
- &party_id.number);
+ &party_id.name, &party_id.number);
}
if (new_subaddress || (party_id.subaddress.valid && new_number)) {
q931_subaddress_transfer(ctrl, call);
@@ -1050,10 +1106,10 @@
* connected yet.
*/
q931_notify_redirection(ctrl, call, PRI_NOTIFY_TRANSFER_ACTIVE,
- &party_id.number);
+ &party_id.name, &party_id.number);
#else
q931_request_subaddress(ctrl, call, PRI_NOTIFY_TRANSFER_ACTIVE,
- &party_id.number);
+ &party_id.name, &party_id.number);
#endif /* defined(USE_NOTIFY_FOR_ECT) */
}
if (new_subaddress || (party_id.subaddress.valid && new_number)) {
@@ -1167,7 +1223,7 @@
* themselves. Well... If you consider someone else picking up
* the handset a redirection then how is the network to know?
*/
- q931_notify_redirection(ctrl, call, PRI_NOTIFY_CALL_DIVERTING,
+ q931_notify_redirection(ctrl, call, PRI_NOTIFY_CALL_DIVERTING, NULL,
&call->redirecting.to.number);
}
break;
@@ -2050,3 +2106,35 @@
ctrl->cc.option.signaling_retention_rsp = signaling_retention ? 1 : 0;
}
}
+
+void pri_display_options_send(struct pri *ctrl, unsigned long flags)
+{
+ if (!ctrl) {
+ return;
+ }
+ if (!flags) {
+ flags = pri_display_options_send_default(ctrl);
+ }
+ ctrl->display_flags.send = flags;
+}
+
+void pri_display_options_receive(struct pri *ctrl, unsigned long flags)
+{
+ if (!ctrl) {
+ return;
+ }
+ if (!flags) {
+ flags = pri_display_options_receive_default(ctrl);
+ }
+ ctrl->display_flags.receive = flags;
+}
+
+int pri_display_text(struct pri *ctrl, q931_call *call, const struct pri_subcmd_display_txt *display)
+{
+ if (!ctrl || !display || display->length <= 0
+ || sizeof(display->text) < display->length || !pri_is_call_valid(ctrl, call)) {
+ /* Parameter sanity checks failed. */
+ return -1;
+ }
+ return q931_display_text(ctrl, call, display);
+}
Modified: branches/1.4/pri_facility.c
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri_facility.c?view=diff&rev=2190&r1=2189&r2=2190
==============================================================================
--- branches/1.4/pri_facility.c (original)
+++ branches/1.4/pri_facility.c Fri Feb 4 13:59:45 2011
@@ -3355,8 +3355,18 @@
*/
int send_call_transfer_complete(struct pri *ctrl, q931_call *call, int call_status)
{
- if (rose_call_transfer_complete_encode(ctrl, call, call_status)
- || q931_facility(ctrl, call)) {
+ int status;
+
+ status = rose_call_transfer_complete_encode(ctrl, call, call_status);
+ if (!status) {
+ if (!call_status && call->local_id.number.valid
+ && (ctrl->display_flags.send & PRI_DISPLAY_OPTION_NAME_UPDATE)) {
+ status = q931_facility_display_name(ctrl, call, &call->local_id.name);
+ } else {
+ status = q931_facility(ctrl, call);
+ }
+ }
+ if (status) {
pri_message(ctrl,
"Could not schedule facility message for call transfer completed.\n");
return -1;
@@ -3574,6 +3584,7 @@
*/
static void etsi_request_subaddress(struct pri *ctrl, struct q931_call *call)
{
+ struct q931_party_name name;
int changed = 0;
switch (call->notify) {
@@ -3585,6 +3596,15 @@
}
/* Fall through */
case PRI_NOTIFY_TRANSFER_ALERTING:
+ if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
+ if (q931_display_name_get(call, &name)) {
+ if (q931_party_name_cmp(&call->remote_id.name, &name)) {
+ /* The remote party name information changed. */
+ call->remote_id.name = name;
+ changed = 1;
+ }
+ }
+ }
if (call->redirection_number.valid
&& q931_party_number_cmp(&call->remote_id.number, &call->redirection_number)) {
/* The remote party number information changed. */
@@ -3626,6 +3646,7 @@
static void handle_subaddress_transfer(struct pri *ctrl, struct q931_call *call, const struct rosePartySubaddress *subaddr)
{
int changed = 0;
+ struct q931_party_name name;
struct q931_party_subaddress q931_subaddress;
q931_party_subaddress_init(&q931_subaddress);
@@ -3639,6 +3660,15 @@
/* The remote party number information changed. */
call->remote_id.number = call->redirection_number;
changed = 1;
+ }
+ if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
+ if (q931_display_name_get(call, &name)) {
+ if (q931_party_name_cmp(&call->remote_id.name, &name)) {
+ /* The remote party name information changed. */
+ call->remote_id.name = name;
+ changed = 1;
+ }
+ }
}
if (changed) {
call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
@@ -4684,6 +4714,10 @@
send_ect_link_id_rsp(ctrl, call, invoke->invoke_id);
break;
case ROSE_ETSI_EctInform:
+ if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
+ q931_display_name_get(call, &call->remote_id.name);
+ }
+
/* redirectionNumber is put in remote_id.number */
if (invoke->args.etsi.EctInform.redirection_present) {
rose_copy_presented_number_unscreened_to_q931(ctrl,
@@ -5002,6 +5036,10 @@
break;
#endif /* Not handled yet */
case ROSE_QSIG_CallingName:
+ if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
+ q931_display_name_get(call, &call->remote_id.name);
+ }
+
/* CallingName is put in remote_id.name */
rose_copy_name_to_q931(ctrl, &call->remote_id.name,
&invoke->args.qsig.CallingName.name);
@@ -5023,6 +5061,10 @@
}
break;
case ROSE_QSIG_CalledName:
+ if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
+ q931_display_name_get(call, &call->remote_id.name);
+ }
+
/* CalledName is put in remote_id.name */
rose_copy_name_to_q931(ctrl, &call->remote_id.name,
&invoke->args.qsig.CalledName.name);
@@ -5044,6 +5086,10 @@
}
break;
case ROSE_QSIG_ConnectedName:
+ if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
+ q931_display_name_get(call, &call->remote_id.name);
+ }
+
/* ConnectedName is put in remote_id.name */
rose_copy_name_to_q931(ctrl, &call->remote_id.name,
&invoke->args.qsig.ConnectedName.name);
@@ -5095,6 +5141,10 @@
break;
#endif /* Not handled yet */
case ROSE_QSIG_CallTransferActive:
+ if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
+ q931_display_name_get(call, &call->remote_id.name);
+ }
+
call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
/* connectedAddress is put in remote_id */
@@ -5108,6 +5158,10 @@
}
break;
case ROSE_QSIG_CallTransferComplete:
+ if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
+ q931_display_name_get(call, &call->remote_id.name);
+ }
+
/* redirectionNumber is put in remote_id.number */
rose_copy_presented_number_screened_to_q931(ctrl, &call->remote_id.number,
&invoke->args.qsig.CallTransferComplete.redirection);
@@ -5138,6 +5192,10 @@
break;
case ROSE_QSIG_CallTransferUpdate:
party_id = call->remote_id;
+
+ if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
+ q931_display_name_get(call, &party_id.name);
+ }
/* redirectionNumber is put in party_id.number */
rose_copy_presented_number_screened_to_q931(ctrl, &party_id.number,
Modified: branches/1.4/pri_internal.h
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri_internal.h?view=diff&rev=2190&r1=2189&r2=2190
==============================================================================
--- branches/1.4/pri_internal.h (original)
+++ branches/1.4/pri_internal.h Fri Feb 4 13:59:45 2011
@@ -59,6 +59,9 @@
/*! Maximum number of facility ie's to handle per incoming message. */
#define MAX_FACILITY_IES 8
+
+/*! Maximum length of sent display text string. (No null terminator.) */
+#define MAX_DISPLAY_TEXT 80
/*! Accumulated pri_message() line until a '\n' is seen on the end. */
struct pri_msg_line {
@@ -177,6 +180,13 @@
/*! Number of facility ie's in the array from the current received message. */
unsigned char count;
} facility;
+ /*! Display text policy handling options. */
+ struct {
+ /*! Send display text policy option flags. */
+ unsigned long send;
+ /*! Receive display text policy option flags. */
+ unsigned long receive;
+ } display_flags;
};
/*! \brief Maximum name length plus null terminator (From ECMA-164) */
@@ -602,6 +612,29 @@
/*! TRUE if outgoing call was already redirected. */
unsigned char initially_redirected;
} cc;
+
+ /*! Display text ie contents. */
+ struct {
+ /*! Display ie text. NULL if not present or consumed as remote name. */
+ const char *text;
+ /*! Length of display text. */
+ unsigned char length;
+ /*!
+ * \brief Character set the text is using.
+ * \details
+ * unknown(0),
+ * iso8859-1(1),
+ * enum-value-withdrawn-by-ITU-T(2)
+ * iso8859-2(3),
+ * iso8859-3(4),
+ * iso8859-4(5),
+ * iso8859-5(6),
+ * iso8859-7(7),
+ * iso10646-BmpString(8),
+ * iso10646-utf-8String(9)
+ */
+ unsigned char char_set;
+ } display;
/* AOC charge requesting on Setup */
int aoc_charging_request;
@@ -938,6 +971,11 @@
void q931_party_id_fixup(const struct pri *ctrl, struct q931_party_id *id);
int q931_party_id_presentation(const struct q931_party_id *id);
+int q931_display_name_get(struct q931_call *call, struct q931_party_name *name);
+int q931_display_text(struct pri *ctrl, struct q931_call *call, const struct pri_subcmd_display_txt *display);
+
+int q931_facility_display_name(struct pri *ctrl, struct q931_call *call, const struct q931_party_name *name);
+
const char *q931_call_state_str(enum Q931_CALL_STATE callstate);
const char *msg2str(int msg);
@@ -948,9 +986,9 @@
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_request_subaddress(struct pri *ctrl, struct q931_call *call, int notify, const struct q931_party_name *name, 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);
+int q931_notify_redirection(struct pri *ctrl, struct q931_call *call, int notify, const struct q931_party_name *name, const struct q931_party_number *number);
struct pri_cc_record *pri_cc_find_by_reference(struct pri *ctrl, unsigned reference_id);
struct pri_cc_record *pri_cc_find_by_linkage(struct pri *ctrl, unsigned linkage_id);
Modified: branches/1.4/q931.c
URL: http://svnview.digium.com/svn/libpri/branches/1.4/q931.c?view=diff&rev=2190&r1=2189&r2=2190
==============================================================================
--- branches/1.4/q931.c (original)
+++ branches/1.4/q931.c Fri Feb 4 13:59:45 2011
@@ -937,6 +937,125 @@
}
/*!
+ * \internal
+ * \brief Clear the display text.
+ *
+ * \param call Q.931 call to clear display text.
+ *
+ * \return Nothing
+ */
+static void q931_display_clear(struct q931_call *call)
+{
+ call->display.text = NULL;
+}
+
+/*!
+ * \internal
+ * \brief Set the display text for the party name.
+ *
+ * \param call Q.931 call to set display text to the party name.
+ *
+ * \return Nothing
+ */
+static void q931_display_name_send(struct q931_call *call, const struct q931_party_name *name)
+{
+ if (name->valid) {
+ switch (name->presentation & PRI_PRES_RESTRICTION) {
+ case PRI_PRES_ALLOWED:
+ call->display.text = (char *) name->str;
+ call->display.length = strlen(name->str);
+ call->display.char_set = name->char_set;
+ break;
+ default:
+ call->display.text = NULL;
+ break;
+ }
+ } else {
+ call->display.text = NULL;
+ }
+}
+
+/*!
+ * \brief Get the display text into the party name.
+ *
+ * \param call Q.931 call to get the display text into the party name.
+ * \param name Party name to fill if there is display text.
+ *
+ * \note
+ * The party name is not touched if there is no display text.
+ *
+ * \note
+ * The display text is consumed.
+ *
+ * \return TRUE if party name filled.
+ */
+int q931_display_name_get(struct q931_call *call, struct q931_party_name *name)
+{
+ if (!call->display.text) {
+ return 0;
+ }
+
+ name->valid = 1;
+ name->char_set = call->display.char_set;
+ if (call->display.length < sizeof(name->str)) {
+ memcpy(name->str, call->display.text, call->display.length);
+ name->str[call->display.length] = '\0';
+ } else {
+ name->str[0] = '\0';
+ }
+ if (name->str[0]) {
+ name->presentation = PRI_PRES_ALLOWED;
+ } else {
+ name->presentation = PRI_PRES_RESTRICTED;
+ }
+
+ /* Mark the display text as consumed. */
+ call->display.text = NULL;
+
+ return 1;
+}
+
+/*!
+ * \internal
+ * \brief Fill a subcmd with any display text.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg.
+ *
+ * \note
+ * The display text is consumed.
+ *
+ * \return Nothing
+ */
+static void q931_display_subcmd(struct pri *ctrl, struct q931_call *call)
+{
+ struct pri_subcommand *subcmd;
+
+ if (call->display.text && call->display.length
+ && (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_TEXT)) {
+ subcmd = q931_alloc_subcommand(ctrl);
+ if (subcmd) {
+ /* Setup display text subcommand */
+ subcmd->cmd = PRI_SUBCMD_DISPLAY_TEXT;
+ subcmd->u.display.char_set = call->display.char_set;
+ if (call->display.length < sizeof(subcmd->u.display.text)) {
+ subcmd->u.display.length = call->display.length;
+ } else {
+ /* Truncate display text and leave room for a null terminator. */
+ subcmd->u.display.length = sizeof(subcmd->u.display.text) - 1;
+ }
+ memcpy(subcmd->u.display.text, call->display.text, subcmd->u.display.length);
+
+ /* Make sure display text is null terminated. */
+ subcmd->u.display.text[subcmd->u.display.length] = '\0';
+ }
+ }
+
+ /* Mark the display text as consumed. */
+ call->display.text = NULL;
+}
+
+/*!
* \brief Find the winning subcall if it exists or current call if not outboundbroadcast.
*
* \param call Starting Q.931 call record of search.
@@ -2435,21 +2554,11 @@
static int receive_display(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
{
- unsigned char *data;
-
- switch (msgtype) {
- case Q931_SETUP:
- case Q931_CONNECT:
- /*
- * Only keep the display message on SETUP and CONNECT messages
- * as the remote name.
- */
- break;
- default:
+ u_int8_t *data;
+
+ if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_BLOCK) {
return 0;
}
-
- call->remote_id.name.valid = 1;
data = ie->data;
if (data[0] & 0x80) {
@@ -2457,14 +2566,10 @@
data++;
len--;
}
- call->remote_id.name.char_set = PRI_CHAR_SET_ISO8859_1;
-
- q931_get_number((unsigned char *) call->remote_id.name.str, sizeof(call->remote_id.name.str), data, len - 2);
- if (call->remote_id.name.str[0]) {
- call->remote_id.name.presentation = PRI_PRES_ALLOWED;
- } else {
- call->remote_id.name.presentation = PRI_PRES_RESTRICTED;
- }
+
+ call->display.text = (char *) data;
+ call->display.length = len - 2;
+ call->display.char_set = PRI_CHAR_SET_ISO8859_1;
return 0;
}
@@ -2473,30 +2578,31 @@
size_t datalen;
int i;
+ if (!call->display.text || !call->display.length) {
+ return 0;
+ }
+ if (ctrl->display_flags.send & PRI_DISPLAY_OPTION_BLOCK) {
+ return 0;
+ }
+
i = 0;
-
- if (!call->local_id.name.valid || !call->local_id.name.str[0]) {
- return 0;
- }
switch (ctrl->switchtype) {
case PRI_SWITCH_QSIG:
- /* Q.SIG supports names */
- return 0;
case PRI_SWITCH_EUROISDN_E1:
case PRI_SWITCH_EUROISDN_T1:
- if (ctrl->localtype == PRI_CPE) {
- return 0;
- }
break;
default:
- /* Prefix name with character set indicator. */
+ /* Prefix text with character set indicator. */
ie->data[0] = 0xb1;
++i;
break;
}
- datalen = strlen(call->local_id.name.str);
- memcpy(ie->data + i, call->local_id.name.str, datalen);
+ datalen = call->display.length;
+ if (MAX_DISPLAY_TEXT < datalen + i) {
+ datalen = MAX_DISPLAY_TEXT - i;
+ }
+ memcpy(ie->data + i, call->display.text, datalen);
return 2 + i + datalen;
}
@@ -4742,20 +4848,27 @@
return send_message(ctrl, c, (pd << 8) | mt, maintenance_service_ies);
}
-static int status_ies[] = { Q931_CAUSE, Q931_IE_CALL_STATE, -1 };
-
static int q931_status(struct pri *ctrl, q931_call *call, int cause)
{
+ static int status_ies[] = {
+ Q931_CAUSE,
+ Q931_IE_CALL_STATE,
+ -1
+ };
+
call->cause = cause;
call->causecode = CODE_CCITT;
call->causeloc = LOC_USER;
return send_message(ctrl, call, Q931_STATUS, status_ies);
}
-static int information_ies[] = { Q931_CALLED_PARTY_NUMBER, -1 };
-
int q931_information(struct pri *ctrl, q931_call *c, char digit)
{
+ static int information_ies[] = {
+ Q931_CALLED_PARTY_NUMBER,
+ -1
+ };
+
c->overlap_digits[0] = digit;
c->overlap_digits[1] = '\0';
@@ -4772,6 +4885,84 @@
return send_message(ctrl, c, Q931_INFORMATION, information_ies);
}
+/*!
+ * \internal
+ * \brief Actually send display text if in the right call state.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg
+ * \param display Display text to send.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int q931_display_text_helper(struct pri *ctrl, struct q931_call *call, const struct pri_subcmd_display_txt *display)
+{
+ int status;
+ static int information_display_ies[] = {
+ Q931_DISPLAY,
+ -1
+ };
+
+ switch (call->ourcallstate) {
+ case Q931_CALL_STATE_OVERLAP_SENDING:
+ case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
+ case Q931_CALL_STATE_CALL_DELIVERED:
+ case Q931_CALL_STATE_CALL_RECEIVED:
+ case Q931_CALL_STATE_CONNECT_REQUEST:
+ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
+ case Q931_CALL_STATE_ACTIVE:
+ case Q931_CALL_STATE_OVERLAP_RECEIVING:
+ call->display.text = display->text;
+ call->display.length = display->length;
+ call->display.char_set = display->char_set;
+ status = send_message(ctrl, call, Q931_INFORMATION, information_display_ies);
+ q931_display_clear(call);
+ break;
+ default:
+ status = 0;
+ break;
+ }
+
+ return status;
+}
+
+/*!
+ * \brief Send display text during a call.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg
+ * \param display Display text to send.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int q931_display_text(struct pri *ctrl, struct q931_call *call, const struct pri_subcmd_display_txt *display)
+{
+ int status;
+ unsigned idx;
+ struct q931_call *subcall;
+
+ if ((ctrl->display_flags.send & (PRI_DISPLAY_OPTION_BLOCK | PRI_DISPLAY_OPTION_TEXT))
+ != PRI_DISPLAY_OPTION_TEXT) {
+ /* Not enabled */
+ return 0;
+ }
+ if (call->outboundbroadcast && call->master_call == call) {
+ status = 0;
+ for (idx = 0; idx < ARRAY_LEN(call->subcalls); ++idx) {
+ subcall = call->subcalls[idx];
+ if (subcall && q931_display_text_helper(ctrl, subcall, display)) {
+ status = -1;
+ }
+ }
+ } else {
+ status = q931_display_text_helper(ctrl, call, display);
+ }
+ return status;
+}
+
+
static int keypad_facility_ies[] = { Q931_IE_KEYPAD_FACILITY, -1 };
int q931_keypad_facility(struct pri *ctrl, q931_call *call, const char *digits)
@@ -4789,41 +4980,66 @@
return send_message(ctrl, c, Q931_RESTART_ACKNOWLEDGE, restart_ack_ies);
}
-static int facility_ies[] = { Q931_IE_FACILITY, -1 };
-
-int q931_facility(struct pri*ctrl, q931_call *c)
-{
- 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
-};
+int q931_facility(struct pri *ctrl, struct q931_call *call)
+{
+ static int facility_ies[] = {
+ Q931_IE_FACILITY,
+ -1
+ };
+
+ return send_message(ctrl, call, Q931_FACILITY, facility_ies);
+}
+
+int q931_facility_display_name(struct pri *ctrl, struct q931_call *call, const struct q931_party_name *name)
+{
+ int status;
+ static int facility_display_ies[] = {
+ Q931_IE_FACILITY,
+ Q931_DISPLAY,
+ -1
+ };
+
+ q931_display_name_send(call, name);
+ status = send_message(ctrl, call, Q931_FACILITY, facility_display_ies);
+ q931_display_clear(call);
+ return status;
+}
/*!
- * \brief Send a FACILITY RequestSubaddress with optional redirection number.
+ * \brief Send a FACILITY RequestSubaddress with optional redirection name and number.
*
* \param ctrl D channel controller.
* \param call Q.931 call leg
* \param notify Notification indicator
+ * \param name Redirection name to send if not NULL.
* \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)
-{
+int q931_request_subaddress(struct pri *ctrl, struct q931_call *call, int notify, const struct q931_party_name *name, const struct q931_party_number *number)
+{
+ int status;
struct q931_call *winner;
+ static int facility_notify_ies[] = {
+ Q931_IE_FACILITY,
+ Q931_IE_NOTIFY_IND,
+ Q931_DISPLAY,
+ Q931_IE_REDIRECTION_NUMBER,
+ -1
+ };
winner = q931_find_winning_call(call);
if (!winner) {
return -1;
}
+ q931_display_clear(winner);
if (number) {
winner->redirection_number = *number;
+ if (number->valid && name
+ && (ctrl->display_flags.send & PRI_DISPLAY_OPTION_NAME_UPDATE)) {
+ q931_display_name_send(winner, name);
+ }
} else {
q931_party_number_init(&winner->redirection_number);
}
@@ -4832,10 +5048,13 @@
|| 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;
+ status = -1;
+ } else {
+ status = 0;
+ }
+ q931_display_clear(winner);
+
+ return status;
}
/*!
@@ -4878,43 +5097,58 @@
return status;
}
-static int notify_ies[] = { Q931_IE_NOTIFY_IND, Q931_IE_REDIRECTION_NUMBER, -1 };
-
/*!
* \internal
- * \brief Actually send a NOTIFY message with optional redirection number.
+ * \brief Actually send a NOTIFY message with optional redirection name and number.
*
* \param ctrl D channel controller.
* \param call Q.931 call leg
* \param notify Notification indicator
+ * \param name Redirection display name to send if not NULL.
* \param number Redirection number to send if not NULL.
*
* \retval 0 on success.
* \retval -1 on error.
*/
-static int q931_notify_redirection_helper(struct pri *ctrl, q931_call *call, int notify, const struct q931_party_number *number)
-{
+static int q931_notify_redirection_helper(struct pri *ctrl, struct q931_call *call, int notify, const struct q931_party_name *name, const struct q931_party_number *number)
+{
+ int status;
+ static int notify_ies[] = {
+ Q931_IE_NOTIFY_IND,
+ Q931_DISPLAY,
+ Q931_IE_REDIRECTION_NUMBER,
+ -1
+ };
+
+ q931_display_clear(call);
if (number) {
call->redirection_number = *number;
+ if (number->valid && name
+ && (ctrl->display_flags.send & PRI_DISPLAY_OPTION_NAME_UPDATE)) {
+ q931_display_name_send(call, name);
+ }
} else {
q931_party_number_init(&call->redirection_number);
}
call->notify = notify;
- return send_message(ctrl, call, Q931_NOTIFY, notify_ies);
+ status = send_message(ctrl, call, Q931_NOTIFY, notify_ies);
+ q931_display_clear(call);
+ return status;
}
/*!
- * \brief Send a NOTIFY message with optional redirection number.
+ * \brief Send a NOTIFY message with optional redirection name and number.
*
* \param ctrl D channel controller.
* \param call Q.931 call leg
* \param notify Notification indicator
+ * \param name Redirection display name to send if not NULL.
* \param number Redirection number to send if not NULL.
*
* \retval 0 on success.
* \retval -1 on error.
*/
-int q931_notify_redirection(struct pri *ctrl, q931_call *call, int notify, const struct q931_party_number *number)
+int q931_notify_redirection(struct pri *ctrl, struct q931_call *call, int notify, const struct q931_party_name *name, const struct q931_party_number *number)
{
int status;
unsigned idx;
@@ -4930,7 +5164,7 @@
case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
case Q931_CALL_STATE_CALL_DELIVERED:
case Q931_CALL_STATE_ACTIVE:
- if (q931_notify_redirection_helper(ctrl, subcall, notify, number)) {
+ if (q931_notify_redirection_helper(ctrl, subcall, notify, name, number)) {
status = -1;
}
break;
@@ -4940,7 +5174,7 @@
}
}
} else {
- status = q931_notify_redirection_helper(ctrl, call, notify, number);
+ status = q931_notify_redirection_helper(ctrl, call, notify, name, number);
}
return status;
}
@@ -4964,7 +5198,7 @@
/* Cannot send NOTIFY message if the mandatory ie is not going to be present. */
return -1;
}
- return q931_notify_redirection(ctrl, c, info, NULL);
+ return q931_notify_redirection(ctrl, c, info, NULL, NULL);
}
#ifdef ALERTING_NO_PROGRESS
@@ -5278,6 +5512,11 @@
default:
break;
}
+ if (ctrl->display_flags.send & PRI_DISPLAY_OPTION_NAME_INITIAL) {
+ q931_display_name_send(c, &c->local_id.name);
+ } else {
+ q931_display_clear(c);
+ }
if (ctrl->localtype == PRI_NETWORK) {
/* networks may send date/time */
return send_message(ctrl, c, Q931_CONNECT, connect_net_ies);
@@ -5473,6 +5712,11 @@
* retransmits will lose the facility ies.
*/
pri_call_add_standard_apdus(ctrl, c);
+ if (ctrl->display_flags.send & PRI_DISPLAY_OPTION_NAME_INITIAL) {
+ q931_display_name_send(c, &c->local_id.name);
+ } else {
+ q931_display_clear(c);
+ }
c->cc.saved_ie_contents.length = 0;
c->cc.saved_ie_flags = 0;
if (ctrl->link.next && !ctrl->bri)
@@ -5567,6 +5811,11 @@
c->aoc_charging_request = req->aoc_charging_request;
pri_call_add_standard_apdus(ctrl, c);
+ if (ctrl->display_flags.send & PRI_DISPLAY_OPTION_NAME_INITIAL) {
+ q931_display_name_send(c, &c->local_id.name);
+ } else {
+ q931_display_clear(c);
+ }
/* Save the initial cc-parties. */
c->cc.party_a = c->local_id;
@@ -6808,7 +7057,8 @@
break;
}
q931_clr_subcommands(ctrl);
-
+ q931_display_clear(c);
+
/* Handle IEs */
memset(mandies, 0, sizeof(mandies));
for (x = 0; x < ARRAY_LEN(msgs); ++x) {
@@ -6830,6 +7080,7 @@
/* Allow the message anyway. We have already processed an ie. */
break;
}
+ q931_display_clear(c);
return -1;
}
for (y = 0; y < ARRAY_LEN(mandies); ++y) {
@@ -6907,6 +7158,17 @@
}
if (!missingmand) {
+ switch (mh->msg) {
+ case Q931_SETUP:
+ case Q931_CONNECT:
+ if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_INITIAL) {
+ q931_display_name_get(c, &c->remote_id.name);
+ }
+ break;
+ default:
+ break;
+ }
+
/* Now handle the facility ie's after all the other ie's were processed. */
q931_handle_facilities(ctrl, c, mh->msg);
}
@@ -6939,6 +7201,8 @@
}
break;
}
+ q931_display_subcmd(ctrl, c);
+ q931_display_clear(c);
return res;
}
@@ -7888,6 +8152,7 @@
default:
break;
}
+ q931_display_subcmd(ctrl, c);
if (ctrl->subcmds.counter_subcmd) {
q931_fill_facility_event(ctrl, c);
return Q931_RES_HAVEEVENT;
@@ -8294,6 +8559,7 @@
}
}
+ q931_display_subcmd(ctrl, c);
if (ctrl->subcmds.counter_subcmd) {
q931_fill_facility_event(ctrl, c);
res = Q931_RES_HAVEEVENT;
@@ -8307,6 +8573,17 @@
}
/* Fall through */
case PRI_NOTIFY_TRANSFER_ALERTING:
+ if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_NAME_UPDATE) {
+ struct q931_party_name name;
+
+ if (q931_display_name_get(c, &name)) {
+ if (q931_party_name_cmp(&c->remote_id.name, &name)) {
+ /* The remote party name information changed. */
+ c->remote_id.name = name;
+ changed = 1;
+ }
+ }
+ }
if (c->redirection_number.valid
&& q931_party_number_cmp(&c->remote_id.number, &c->redirection_number)) {
/* The remote party number information changed. */
@@ -8331,6 +8608,7 @@
}
}
+ q931_display_subcmd(ctrl, c);
if (ctrl->subcmds.counter_subcmd) {
q931_fill_facility_event(ctrl, c);
res = Q931_RES_HAVEEVENT;
More information about the libpri-commits
mailing list