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
This commit is contained in:
parent
d0dbd5b3f2
commit
ed0d76d538
80
libpri.h
80
libpri.h
@ -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_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_REQ 23 /*!< Malicious Call ID Request */
|
||||||
#define PRI_SUBCMD_MCID_RSP 24 /*!< Malicious Call ID Request response */
|
#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)
|
#if defined(STATUS_REQUEST_PLACE_HOLDER)
|
||||||
struct pri_subcmd_status_request {
|
struct pri_subcmd_status_request {
|
||||||
@ -967,6 +968,35 @@ struct pri_subcmd_mcid_rsp {
|
|||||||
int fail_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 {
|
struct pri_subcommand {
|
||||||
/*! PRI_SUBCMD_xxx defined values */
|
/*! PRI_SUBCMD_xxx defined values */
|
||||||
int cmd;
|
int cmd;
|
||||||
@ -999,6 +1029,7 @@ struct pri_subcommand {
|
|||||||
struct pri_subcmd_aoc_e aoc_e;
|
struct pri_subcmd_aoc_e aoc_e;
|
||||||
struct pri_subcmd_mcid_req mcid_req;
|
struct pri_subcmd_mcid_req mcid_req;
|
||||||
struct pri_subcmd_mcid_rsp mcid_rsp;
|
struct pri_subcmd_mcid_rsp mcid_rsp;
|
||||||
|
struct pri_subcmd_display_txt display;
|
||||||
} u;
|
} 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);
|
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.
|
* \brief Set the call hold feature enable flag.
|
||||||
*
|
*
|
||||||
|
96
pri.c
96
pri.c
@ -288,6 +288,60 @@ static int __pri_write(struct pri *pri, void *buf, int buflen)
|
|||||||
return res;
|
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.
|
* \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_rxcount = 0;
|
||||||
ctrl->q931_txcount = 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) {
|
switch (switchtype) {
|
||||||
case PRI_SWITCH_GR303_EOC:
|
case PRI_SWITCH_GR303_EOC:
|
||||||
ctrl->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
|
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) {
|
if (new_number) {
|
||||||
q931_notify_redirection(ctrl, call, PRI_NOTIFY_TRANSFER_ACTIVE,
|
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)) {
|
if (new_subaddress || (party_id.subaddress.valid && new_number)) {
|
||||||
q931_subaddress_transfer(ctrl, call);
|
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.
|
* connected yet.
|
||||||
*/
|
*/
|
||||||
q931_notify_redirection(ctrl, call, PRI_NOTIFY_TRANSFER_ACTIVE,
|
q931_notify_redirection(ctrl, call, PRI_NOTIFY_TRANSFER_ACTIVE,
|
||||||
&party_id.number);
|
&party_id.name, &party_id.number);
|
||||||
#else
|
#else
|
||||||
q931_request_subaddress(ctrl, call, PRI_NOTIFY_TRANSFER_ACTIVE,
|
q931_request_subaddress(ctrl, call, PRI_NOTIFY_TRANSFER_ACTIVE,
|
||||||
&party_id.number);
|
&party_id.name, &party_id.number);
|
||||||
#endif /* defined(USE_NOTIFY_FOR_ECT) */
|
#endif /* defined(USE_NOTIFY_FOR_ECT) */
|
||||||
}
|
}
|
||||||
if (new_subaddress || (party_id.subaddress.valid && new_number)) {
|
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
|
* themselves. Well... If you consider someone else picking up
|
||||||
* the handset a redirection then how is the network to know?
|
* 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);
|
&call->redirecting.to.number);
|
||||||
}
|
}
|
||||||
break;
|
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;
|
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)
|
int send_call_transfer_complete(struct pri *ctrl, q931_call *call, int call_status)
|
||||||
{
|
{
|
||||||
if (rose_call_transfer_complete_encode(ctrl, call, call_status)
|
int status;
|
||||||
|| q931_facility(ctrl, call)) {
|
|
||||||
|
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,
|
pri_message(ctrl,
|
||||||
"Could not schedule facility message for call transfer completed.\n");
|
"Could not schedule facility message for call transfer completed.\n");
|
||||||
return -1;
|
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)
|
static void etsi_request_subaddress(struct pri *ctrl, struct q931_call *call)
|
||||||
{
|
{
|
||||||
|
struct q931_party_name name;
|
||||||
int changed = 0;
|
int changed = 0;
|
||||||
|
|
||||||
switch (call->notify) {
|
switch (call->notify) {
|
||||||
@ -3585,6 +3596,15 @@ static void etsi_request_subaddress(struct pri *ctrl, struct q931_call *call)
|
|||||||
}
|
}
|
||||||
/* Fall through */
|
/* Fall through */
|
||||||
case PRI_NOTIFY_TRANSFER_ALERTING:
|
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
|
if (call->redirection_number.valid
|
||||||
&& q931_party_number_cmp(&call->remote_id.number, &call->redirection_number)) {
|
&& q931_party_number_cmp(&call->remote_id.number, &call->redirection_number)) {
|
||||||
/* The remote party number information changed. */
|
/* 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)
|
static void handle_subaddress_transfer(struct pri *ctrl, struct q931_call *call, const struct rosePartySubaddress *subaddr)
|
||||||
{
|
{
|
||||||
int changed = 0;
|
int changed = 0;
|
||||||
|
struct q931_party_name name;
|
||||||
struct q931_party_subaddress q931_subaddress;
|
struct q931_party_subaddress q931_subaddress;
|
||||||
|
|
||||||
q931_party_subaddress_init(&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;
|
call->remote_id.number = call->redirection_number;
|
||||||
changed = 1;
|
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) {
|
if (changed) {
|
||||||
call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
|
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);
|
send_ect_link_id_rsp(ctrl, call, invoke->invoke_id);
|
||||||
break;
|
break;
|
||||||
case ROSE_ETSI_EctInform:
|
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 */
|
/* redirectionNumber is put in remote_id.number */
|
||||||
if (invoke->args.etsi.EctInform.redirection_present) {
|
if (invoke->args.etsi.EctInform.redirection_present) {
|
||||||
rose_copy_presented_number_unscreened_to_q931(ctrl,
|
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;
|
break;
|
||||||
#endif /* Not handled yet */
|
#endif /* Not handled yet */
|
||||||
case ROSE_QSIG_CallingName:
|
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 */
|
/* CallingName is put in remote_id.name */
|
||||||
rose_copy_name_to_q931(ctrl, &call->remote_id.name,
|
rose_copy_name_to_q931(ctrl, &call->remote_id.name,
|
||||||
&invoke->args.qsig.CallingName.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;
|
break;
|
||||||
case ROSE_QSIG_CalledName:
|
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 */
|
/* CalledName is put in remote_id.name */
|
||||||
rose_copy_name_to_q931(ctrl, &call->remote_id.name,
|
rose_copy_name_to_q931(ctrl, &call->remote_id.name,
|
||||||
&invoke->args.qsig.CalledName.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;
|
break;
|
||||||
case ROSE_QSIG_ConnectedName:
|
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 */
|
/* ConnectedName is put in remote_id.name */
|
||||||
rose_copy_name_to_q931(ctrl, &call->remote_id.name,
|
rose_copy_name_to_q931(ctrl, &call->remote_id.name,
|
||||||
&invoke->args.qsig.ConnectedName.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;
|
break;
|
||||||
#endif /* Not handled yet */
|
#endif /* Not handled yet */
|
||||||
case ROSE_QSIG_CallTransferActive:
|
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;
|
call->incoming_ct_state = INCOMING_CT_STATE_POST_CONNECTED_LINE;
|
||||||
|
|
||||||
/* connectedAddress is put in remote_id */
|
/* 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;
|
break;
|
||||||
case ROSE_QSIG_CallTransferComplete:
|
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 */
|
/* redirectionNumber is put in remote_id.number */
|
||||||
rose_copy_presented_number_screened_to_q931(ctrl, &call->remote_id.number,
|
rose_copy_presented_number_screened_to_q931(ctrl, &call->remote_id.number,
|
||||||
&invoke->args.qsig.CallTransferComplete.redirection);
|
&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:
|
case ROSE_QSIG_CallTransferUpdate:
|
||||||
party_id = call->remote_id;
|
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 */
|
/* redirectionNumber is put in party_id.number */
|
||||||
rose_copy_presented_number_screened_to_q931(ctrl, &party_id.number,
|
rose_copy_presented_number_screened_to_q931(ctrl, &party_id.number,
|
||||||
&invoke->args.qsig.CallTransferUpdate.redirection);
|
&invoke->args.qsig.CallTransferUpdate.redirection);
|
||||||
|
@ -60,6 +60,9 @@ struct pri_sched {
|
|||||||
/*! Maximum number of facility ie's to handle per incoming message. */
|
/*! Maximum number of facility ie's to handle per incoming message. */
|
||||||
#define MAX_FACILITY_IES 8
|
#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. */
|
/*! Accumulated pri_message() line until a '\n' is seen on the end. */
|
||||||
struct pri_msg_line {
|
struct pri_msg_line {
|
||||||
/*! Accumulated buffer used. */
|
/*! Accumulated buffer used. */
|
||||||
@ -177,6 +180,13 @@ struct pri {
|
|||||||
/*! Number of facility ie's in the array from the current received message. */
|
/*! Number of facility ie's in the array from the current received message. */
|
||||||
unsigned char count;
|
unsigned char count;
|
||||||
} facility;
|
} 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) */
|
/*! \brief Maximum name length plus null terminator (From ECMA-164) */
|
||||||
@ -603,6 +613,29 @@ struct q931_call {
|
|||||||
unsigned char initially_redirected;
|
unsigned char initially_redirected;
|
||||||
} cc;
|
} 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 */
|
/* AOC charge requesting on Setup */
|
||||||
int aoc_charging_request;
|
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);
|
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_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 *q931_call_state_str(enum Q931_CALL_STATE callstate);
|
||||||
const char *msg2str(int msg);
|
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_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);
|
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_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_reference(struct pri *ctrl, unsigned reference_id);
|
||||||
struct pri_cc_record *pri_cc_find_by_linkage(struct pri *ctrl, unsigned linkage_id);
|
struct pri_cc_record *pri_cc_find_by_linkage(struct pri *ctrl, unsigned linkage_id);
|
||||||
|
390
q931.c
390
q931.c
@ -936,6 +936,125 @@ int q931_party_id_presentation(const struct q931_party_id *id)
|
|||||||
return number_value | number_screening;
|
return number_value | number_screening;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \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.
|
* \brief Find the winning subcall if it exists or current call if not outboundbroadcast.
|
||||||
*
|
*
|
||||||
@ -2435,36 +2554,22 @@ static void dump_progress_indicator(int full_ie, struct pri *ctrl, q931_ie *ie,
|
|||||||
|
|
||||||
static int receive_display(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
|
static int receive_display(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
|
||||||
{
|
{
|
||||||
unsigned char *data;
|
u_int8_t *data;
|
||||||
|
|
||||||
switch (msgtype) {
|
if (ctrl->display_flags.receive & PRI_DISPLAY_OPTION_BLOCK) {
|
||||||
case Q931_SETUP:
|
|
||||||
case Q931_CONNECT:
|
|
||||||
/*
|
|
||||||
* Only keep the display message on SETUP and CONNECT messages
|
|
||||||
* as the remote name.
|
|
||||||
*/
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
call->remote_id.name.valid = 1;
|
|
||||||
|
|
||||||
data = ie->data;
|
data = ie->data;
|
||||||
if (data[0] & 0x80) {
|
if (data[0] & 0x80) {
|
||||||
/* Skip over character set */
|
/* Skip over character set */
|
||||||
data++;
|
data++;
|
||||||
len--;
|
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);
|
call->display.text = (char *) data;
|
||||||
if (call->remote_id.name.str[0]) {
|
call->display.length = len - 2;
|
||||||
call->remote_id.name.presentation = PRI_PRES_ALLOWED;
|
call->display.char_set = PRI_CHAR_SET_ISO8859_1;
|
||||||
} else {
|
|
||||||
call->remote_id.name.presentation = PRI_PRES_RESTRICTED;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2473,30 +2578,31 @@ static int transmit_display(int full_ie, struct pri *ctrl, q931_call *call, int
|
|||||||
size_t datalen;
|
size_t datalen;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
i = 0;
|
if (!call->display.text || !call->display.length) {
|
||||||
|
|
||||||
if (!call->local_id.name.valid || !call->local_id.name.str[0]) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (ctrl->display_flags.send & PRI_DISPLAY_OPTION_BLOCK) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
switch (ctrl->switchtype) {
|
switch (ctrl->switchtype) {
|
||||||
case PRI_SWITCH_QSIG:
|
case PRI_SWITCH_QSIG:
|
||||||
/* Q.SIG supports names */
|
|
||||||
return 0;
|
|
||||||
case PRI_SWITCH_EUROISDN_E1:
|
case PRI_SWITCH_EUROISDN_E1:
|
||||||
case PRI_SWITCH_EUROISDN_T1:
|
case PRI_SWITCH_EUROISDN_T1:
|
||||||
if (ctrl->localtype == PRI_CPE) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Prefix name with character set indicator. */
|
/* Prefix text with character set indicator. */
|
||||||
ie->data[0] = 0xb1;
|
ie->data[0] = 0xb1;
|
||||||
++i;
|
++i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
datalen = strlen(call->local_id.name.str);
|
datalen = call->display.length;
|
||||||
memcpy(ie->data + i, call->local_id.name.str, datalen);
|
if (MAX_DISPLAY_TEXT < datalen + i) {
|
||||||
|
datalen = MAX_DISPLAY_TEXT - i;
|
||||||
|
}
|
||||||
|
memcpy(ie->data + i, call->display.text, datalen);
|
||||||
return 2 + i + datalen;
|
return 2 + i + datalen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4742,20 +4848,27 @@ int maintenance_service(struct pri *ctrl, int span, int channel, int changestatu
|
|||||||
return send_message(ctrl, c, (pd << 8) | mt, maintenance_service_ies);
|
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 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->cause = cause;
|
||||||
call->causecode = CODE_CCITT;
|
call->causecode = CODE_CCITT;
|
||||||
call->causeloc = LOC_USER;
|
call->causeloc = LOC_USER;
|
||||||
return send_message(ctrl, call, Q931_STATUS, status_ies);
|
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)
|
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[0] = digit;
|
||||||
c->overlap_digits[1] = '\0';
|
c->overlap_digits[1] = '\0';
|
||||||
|
|
||||||
@ -4772,6 +4885,84 @@ int q931_information(struct pri *ctrl, q931_call *c, char digit)
|
|||||||
return send_message(ctrl, c, Q931_INFORMATION, information_ies);
|
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 };
|
static int keypad_facility_ies[] = { Q931_IE_KEYPAD_FACILITY, -1 };
|
||||||
|
|
||||||
int q931_keypad_facility(struct pri *ctrl, q931_call *call, const char *digits)
|
int q931_keypad_facility(struct pri *ctrl, q931_call *call, const char *digits)
|
||||||
@ -4789,41 +4980,66 @@ static int restart_ack(struct pri *ctrl, q931_call *c)
|
|||||||
return send_message(ctrl, c, Q931_RESTART_ACKNOWLEDGE, restart_ack_ies);
|
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, struct q931_call *call)
|
||||||
|
|
||||||
int q931_facility(struct pri*ctrl, q931_call *c)
|
|
||||||
{
|
{
|
||||||
return send_message(ctrl, c, Q931_FACILITY, facility_ies);
|
static int facility_ies[] = {
|
||||||
|
Q931_IE_FACILITY,
|
||||||
|
-1
|
||||||
|
};
|
||||||
|
|
||||||
|
return send_message(ctrl, call, Q931_FACILITY, facility_ies);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int facility_notify_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_IE_FACILITY,
|
||||||
Q931_IE_NOTIFY_IND,
|
Q931_DISPLAY,
|
||||||
Q931_IE_REDIRECTION_NUMBER,
|
|
||||||
-1
|
-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 ctrl D channel controller.
|
||||||
* \param call Q.931 call leg
|
* \param call Q.931 call leg
|
||||||
* \param notify Notification indicator
|
* \param notify Notification indicator
|
||||||
|
* \param name Redirection name to send if not NULL.
|
||||||
* \param number Redirection number to send if not NULL.
|
* \param number Redirection number to send if not NULL.
|
||||||
*
|
*
|
||||||
* \retval 0 on success.
|
* \retval 0 on success.
|
||||||
* \retval -1 on error.
|
* \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;
|
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);
|
winner = q931_find_winning_call(call);
|
||||||
if (!winner) {
|
if (!winner) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
q931_display_clear(winner);
|
||||||
if (number) {
|
if (number) {
|
||||||
winner->redirection_number = *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 {
|
} else {
|
||||||
q931_party_number_init(&winner->redirection_number);
|
q931_party_number_init(&winner->redirection_number);
|
||||||
}
|
}
|
||||||
@ -4832,10 +5048,13 @@ int q931_request_subaddress(struct pri *ctrl, struct q931_call *call, int notify
|
|||||||
|| send_message(ctrl, winner, Q931_FACILITY, facility_notify_ies)) {
|
|| send_message(ctrl, winner, Q931_FACILITY, facility_notify_ies)) {
|
||||||
pri_message(ctrl,
|
pri_message(ctrl,
|
||||||
"Could not schedule facility message for request subaddress.\n");
|
"Could not schedule facility message for request subaddress.\n");
|
||||||
return -1;
|
status = -1;
|
||||||
|
} else {
|
||||||
|
status = 0;
|
||||||
}
|
}
|
||||||
|
q931_display_clear(winner);
|
||||||
|
|
||||||
return 0;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -4878,43 +5097,58 @@ int q931_subaddress_transfer(struct pri *ctrl, struct q931_call *call)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int notify_ies[] = { Q931_IE_NOTIFY_IND, Q931_IE_REDIRECTION_NUMBER, -1 };
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \internal
|
* \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 ctrl D channel controller.
|
||||||
* \param call Q.931 call leg
|
* \param call Q.931 call leg
|
||||||
* \param notify Notification indicator
|
* \param notify Notification indicator
|
||||||
|
* \param name Redirection display name to send if not NULL.
|
||||||
* \param number Redirection number to send if not NULL.
|
* \param number Redirection number to send if not NULL.
|
||||||
*
|
*
|
||||||
* \retval 0 on success.
|
* \retval 0 on success.
|
||||||
* \retval -1 on error.
|
* \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) {
|
if (number) {
|
||||||
call->redirection_number = *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 {
|
} else {
|
||||||
q931_party_number_init(&call->redirection_number);
|
q931_party_number_init(&call->redirection_number);
|
||||||
}
|
}
|
||||||
call->notify = notify;
|
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 ctrl D channel controller.
|
||||||
* \param call Q.931 call leg
|
* \param call Q.931 call leg
|
||||||
* \param notify Notification indicator
|
* \param notify Notification indicator
|
||||||
|
* \param name Redirection display name to send if not NULL.
|
||||||
* \param number Redirection number to send if not NULL.
|
* \param number Redirection number to send if not NULL.
|
||||||
*
|
*
|
||||||
* \retval 0 on success.
|
* \retval 0 on success.
|
||||||
* \retval -1 on error.
|
* \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;
|
int status;
|
||||||
unsigned idx;
|
unsigned idx;
|
||||||
@ -4930,7 +5164,7 @@ int q931_notify_redirection(struct pri *ctrl, q931_call *call, int notify, const
|
|||||||
case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
|
case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
|
||||||
case Q931_CALL_STATE_CALL_DELIVERED:
|
case Q931_CALL_STATE_CALL_DELIVERED:
|
||||||
case Q931_CALL_STATE_ACTIVE:
|
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;
|
status = -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -4940,7 +5174,7 @@ int q931_notify_redirection(struct pri *ctrl, q931_call *call, int notify, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
status = q931_notify_redirection_helper(ctrl, call, notify, number);
|
status = q931_notify_redirection_helper(ctrl, call, notify, name, number);
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -4964,7 +5198,7 @@ int q931_notify(struct pri *ctrl, q931_call *c, int channel, int info)
|
|||||||
/* Cannot send NOTIFY message if the mandatory ie is not going to be present. */
|
/* Cannot send NOTIFY message if the mandatory ie is not going to be present. */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return q931_notify_redirection(ctrl, c, info, NULL);
|
return q931_notify_redirection(ctrl, c, info, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ALERTING_NO_PROGRESS
|
#ifdef ALERTING_NO_PROGRESS
|
||||||
@ -5278,6 +5512,11 @@ int q931_connect(struct pri *ctrl, q931_call *c, int channel, int nonisdn)
|
|||||||
default:
|
default:
|
||||||
break;
|
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) {
|
if (ctrl->localtype == PRI_NETWORK) {
|
||||||
/* networks may send date/time */
|
/* networks may send date/time */
|
||||||
return send_message(ctrl, c, Q931_CONNECT, connect_net_ies);
|
return send_message(ctrl, c, Q931_CONNECT, connect_net_ies);
|
||||||
@ -5473,6 +5712,11 @@ static void t303_expiry(void *data)
|
|||||||
* retransmits will lose the facility ies.
|
* retransmits will lose the facility ies.
|
||||||
*/
|
*/
|
||||||
pri_call_add_standard_apdus(ctrl, c);
|
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_contents.length = 0;
|
||||||
c->cc.saved_ie_flags = 0;
|
c->cc.saved_ie_flags = 0;
|
||||||
if (ctrl->link.next && !ctrl->bri)
|
if (ctrl->link.next && !ctrl->bri)
|
||||||
@ -5567,6 +5811,11 @@ int q931_setup(struct pri *ctrl, q931_call *c, struct pri_sr *req)
|
|||||||
c->aoc_charging_request = req->aoc_charging_request;
|
c->aoc_charging_request = req->aoc_charging_request;
|
||||||
|
|
||||||
pri_call_add_standard_apdus(ctrl, c);
|
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. */
|
/* Save the initial cc-parties. */
|
||||||
c->cc.party_a = c->local_id;
|
c->cc.party_a = c->local_id;
|
||||||
@ -6808,6 +7057,7 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
q931_clr_subcommands(ctrl);
|
q931_clr_subcommands(ctrl);
|
||||||
|
q931_display_clear(c);
|
||||||
|
|
||||||
/* Handle IEs */
|
/* Handle IEs */
|
||||||
memset(mandies, 0, sizeof(mandies));
|
memset(mandies, 0, sizeof(mandies));
|
||||||
@ -6830,6 +7080,7 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
|
|||||||
/* Allow the message anyway. We have already processed an ie. */
|
/* Allow the message anyway. We have already processed an ie. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
q931_display_clear(c);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
for (y = 0; y < ARRAY_LEN(mandies); ++y) {
|
for (y = 0; y < ARRAY_LEN(mandies); ++y) {
|
||||||
@ -6907,6 +7158,17 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!missingmand) {
|
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. */
|
/* Now handle the facility ie's after all the other ie's were processed. */
|
||||||
q931_handle_facilities(ctrl, c, mh->msg);
|
q931_handle_facilities(ctrl, c, mh->msg);
|
||||||
}
|
}
|
||||||
@ -6939,6 +7201,8 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
q931_display_subcmd(ctrl, c);
|
||||||
|
q931_display_clear(c);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7888,6 +8152,7 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
q931_display_subcmd(ctrl, c);
|
||||||
if (ctrl->subcmds.counter_subcmd) {
|
if (ctrl->subcmds.counter_subcmd) {
|
||||||
q931_fill_facility_event(ctrl, c);
|
q931_fill_facility_event(ctrl, c);
|
||||||
return Q931_RES_HAVEEVENT;
|
return Q931_RES_HAVEEVENT;
|
||||||
@ -8294,6 +8559,7 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
q931_display_subcmd(ctrl, c);
|
||||||
if (ctrl->subcmds.counter_subcmd) {
|
if (ctrl->subcmds.counter_subcmd) {
|
||||||
q931_fill_facility_event(ctrl, c);
|
q931_fill_facility_event(ctrl, c);
|
||||||
res = Q931_RES_HAVEEVENT;
|
res = Q931_RES_HAVEEVENT;
|
||||||
@ -8307,6 +8573,17 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
|||||||
}
|
}
|
||||||
/* Fall through */
|
/* Fall through */
|
||||||
case PRI_NOTIFY_TRANSFER_ALERTING:
|
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
|
if (c->redirection_number.valid
|
||||||
&& q931_party_number_cmp(&c->remote_id.number, &c->redirection_number)) {
|
&& q931_party_number_cmp(&c->remote_id.number, &c->redirection_number)) {
|
||||||
/* The remote party number information changed. */
|
/* The remote party number information changed. */
|
||||||
@ -8331,6 +8608,7 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
q931_display_subcmd(ctrl, c);
|
||||||
if (ctrl->subcmds.counter_subcmd) {
|
if (ctrl->subcmds.counter_subcmd) {
|
||||||
q931_fill_facility_event(ctrl, c);
|
q931_fill_facility_event(ctrl, c);
|
||||||
res = Q931_RES_HAVEEVENT;
|
res = Q931_RES_HAVEEVENT;
|
||||||
|
Loading…
Reference in New Issue
Block a user