Commit ed0d76d5 authored by Richard Mudgett's avatar Richard Mudgett

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.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2190 2fbb986a-6c06-0410-b554-c9c1f0a7f128
parent d0dbd5b3
......@@ -547,6 +547,7 @@ struct pri_rerouting_data {
#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 {
......@@ -967,6 +968,35 @@ struct pri_subcmd_mcid_rsp {
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 {
/*! PRI_SUBCMD_xxx defined values */
int cmd;
......@@ -999,6 +1029,7 @@ struct pri_subcommand {
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 @@ int pri_transfer_rsp(struct pri *ctrl, q931_call *call, int invoke_id, int is_su
*/
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.
*
......
......@@ -288,6 +288,60 @@ static int __pri_write(struct pri *pri, void *buf, int buflen)
return res;
}
/*!
* \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.
*
......@@ -481,6 +535,8 @@ static struct pri *pri_ctrl_new(int fd, int node, int switchtype, pri_io_cb rd,
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 @@ int pri_connected_line_update(struct pri *ctrl, q931_call *call, const struct pr
*/
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 @@ int pri_connected_line_update(struct pri *ctrl, q931_call *call, const struct pr
* 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 @@ int pri_redirecting_update(struct pri *ctrl, q931_call *call, const struct pri_p
* 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 @@ void pri_cc_retain_signaling_rsp(struct pri *ctrl, int signaling_retention)
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);
}
......@@ -3355,8 +3355,18 @@ int pri_call_add_standard_apdus(struct pri *ctrl, q931_call *call)
*/
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 @@ int send_subaddress_transfer(struct pri *ctrl, struct q931_call *call)
*/
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 @@ static void etsi_request_subaddress(struct pri *ctrl, struct q931_call *call)
}
/* 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 etsi_request_subaddress(struct pri *ctrl, struct q931_call *call)
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);
......@@ -3640,6 +3661,15 @@ static void handle_subaddress_transfer(struct pri *ctrl, struct q931_call *call,
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 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
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 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
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 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
}
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 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
}
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 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
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 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
}
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);
......@@ -5139,6 +5193,10 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
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,
&invoke->args.qsig.CallTransferUpdate.redirection);
......
......@@ -60,6 +60,9 @@ struct pri_sched {
/*! 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 {
/*! Accumulated buffer used. */
......@@ -177,6 +180,13 @@ struct pri {
/*! 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) */
......@@ -603,6 +613,29 @@ struct q931_call {
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 pri_copy_party_id_to_q931(struct q931_party_id *q931_id, const struct pri_p
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 pri_subcommand *q931_alloc_subcommand(struct pri *ctrl);
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);
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment