Problems with ISDN MWI to phones.

1) The "controlling user number" is always the number of the voice mail box
which is identical with the subscriber number itself.  This number which
is listed in the ISDN phone MWI menu cannot be called back to contact the
voice mail box.  The controlling user number should be made configurable.

2) The MWI indication is not restricted to a user (broadcast facility with
dummy call reference).  A called party IE should be added to address only
the relevant MSN.  (ETSI 300-196 Section 8.3.2.4)

JIRA ABE-2738
JIRA SWP-2846


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2262 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
Richard Mudgett 2011-04-18 19:43:47 +00:00
parent c794af652e
commit 239f8186ef
4 changed files with 112 additions and 34 deletions

View File

@ -1621,11 +1621,11 @@ int pri_mwi_deactivate(struct pri *pri, q931_call *c, char *caller, int callerpl
* \brief Send a MWI indication on the specified D channel. * \brief Send a MWI indication on the specified D channel.
* *
* \param ctrl D channel controller. * \param ctrl D channel controller.
* \param mailbox Controlling party number (NULL if not present). * \param mailbox Party receiving notification.
* \param basic_service Basic service enum (-1 if not present). * \param basic_service Basic service enum (-1 if not present).
* \param num_messages NumberOfMessages (-1 if not present). * \param num_messages NumberOfMessages (-1 if not present).
* \param caller_id Controlling party privided number (NULL if not present). * \param caller_id Party leaving message (NULL if not present).
* \param timestamp Generalized Time format (NULL if not present). * \param timestamp When message left. (Generalized Time format, NULL if not present)
* \param message_reference Message reference number (-1 if not present). * \param message_reference Message reference number (-1 if not present).
* \param message_status Message status: added(0), removed(1). * \param message_status Message status: added(0), removed(1).
* *
@ -1636,6 +1636,27 @@ int pri_mwi_indicate(struct pri *ctrl, const struct pri_party_id *mailbox,
int basic_service, int num_messages, const struct pri_party_id *caller_id, int basic_service, int num_messages, const struct pri_party_id *caller_id,
const char *timestamp, int message_reference, int message_status); const char *timestamp, int message_reference, int message_status);
/*!
* \brief Send a MWI indication on the specified D channel. (Take two)
*
* \param ctrl D channel controller.
* \param mailbox Party receiving notification.
* \param vm_id Voicemail system number (NULL if not present).
* \param basic_service Basic service enum (-1 if not present).
* \param num_messages NumberOfMessages (-1 if not present).
* \param caller_id Party leaving message (NULL if not present).
* \param timestamp When message left. (Generalized Time format, NULL if not present)
* \param message_reference Message reference number (-1 if not present).
* \param message_status Message status: added(0), removed(1).
*
* \retval 0 on success.
* \retval -1 on error.
*/
int pri_mwi_indicate_v2(struct pri *ctrl, const struct pri_party_id *mailbox,
const struct pri_party_id *vm_id, int basic_service, int num_messages,
const struct pri_party_id *caller_id, const char *timestamp, int message_reference,
int message_status);
/* Set service message support flag */ /* Set service message support flag */
int pri_set_service_message_support(struct pri *pri, int supportflag); int pri_set_service_message_support(struct pri *pri, int supportflag);

View File

@ -1746,11 +1746,11 @@ int mwi_message_send(struct pri *ctrl, q931_call *call, struct pri_sr *req, int
* \param ctrl D channel controller for diagnostic messages or global options. * \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode the facility ie contents. * \param pos Starting position to encode the facility ie contents.
* \param end End of facility ie contents encoding data buffer. * \param end End of facility ie contents encoding data buffer.
* \param mailbox Controlling party number (NULL if not present). * \param vm_id Controlling party number (NULL if not present).
* \param basic_service Basic service enum (-1 if not present). * \param basic_service Basic service enum (-1 if not present).
* \param num_messages NumberOfMessages (-1 if not present). * \param num_messages NumberOfMessages (-1 if not present).
* \param caller_id Controlling party privided number (NULL if not present). * \param caller_id Controlling party privided number (NULL if not present).
* \param timestamp Generalized Time format (NULL if not present). * \param timestamp When message left. (Generalized Time format, NULL if not present)
* \param message_reference Message reference number (-1 if not present). * \param message_reference Message reference number (-1 if not present).
* \param message_status Message status: added(0), removed(1). * \param message_status Message status: added(0), removed(1).
* *
@ -1758,7 +1758,7 @@ int mwi_message_send(struct pri *ctrl, q931_call *call, struct pri_sr *req, int
* \retval NULL on error. * \retval NULL on error.
*/ */
static unsigned char *enc_etsi_mwi_indicate_message(struct pri *ctrl, unsigned char *pos, static unsigned char *enc_etsi_mwi_indicate_message(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct pri_party_id *mailbox, int basic_service, unsigned char *end, const struct pri_party_id *vm_id, int basic_service,
int num_messages, const struct pri_party_id *caller_id, const char *timestamp, int num_messages, const struct pri_party_id *caller_id, const char *timestamp,
int message_reference, int message_status) int message_reference, int message_status)
{ {
@ -1774,8 +1774,8 @@ static unsigned char *enc_etsi_mwi_indicate_message(struct pri *ctrl, unsigned c
msg.operation = ROSE_ETSI_MWIIndicate; msg.operation = ROSE_ETSI_MWIIndicate;
msg.invoke_id = get_invokeid(ctrl); msg.invoke_id = get_invokeid(ctrl);
if (mailbox && mailbox->number.valid) { if (vm_id && vm_id->number.valid) {
pri_copy_party_number_to_q931(&number, &mailbox->number); pri_copy_party_number_to_q931(&number, &vm_id->number);
q931_copy_number_to_rose(ctrl, &msg.args.etsi.MWIIndicate.controlling_user_number, q931_copy_number_to_rose(ctrl, &msg.args.etsi.MWIIndicate.controlling_user_number,
&number); &number);
} }
@ -1814,11 +1814,11 @@ static unsigned char *enc_etsi_mwi_indicate_message(struct pri *ctrl, unsigned c
* *
* \param ctrl D channel controller. * \param ctrl D channel controller.
* \param call Call leg to queue message. * \param call Call leg to queue message.
* \param mailbox Controlling party number (NULL if not present). * \param vm_id Voicemail system number (NULL if not present).
* \param basic_service Basic service enum (-1 if not present). * \param basic_service Basic service enum (-1 if not present).
* \param num_messages NumberOfMessages (-1 if not present). * \param num_messages NumberOfMessages (-1 if not present).
* \param caller_id Controlling party privided number (NULL if not present). * \param caller_id Party leaving message (NULL if not present).
* \param timestamp Generalized Time format (NULL if not present). * \param timestamp When message left. (Generalized Time format, NULL if not present)
* \param message_reference Message reference number (-1 if not present). * \param message_reference Message reference number (-1 if not present).
* \param message_status Message status: added(0), removed(1). * \param message_status Message status: added(0), removed(1).
* *
@ -1826,14 +1826,14 @@ static unsigned char *enc_etsi_mwi_indicate_message(struct pri *ctrl, unsigned c
* \retval -1 on error. * \retval -1 on error.
*/ */
static int rose_mwi_indicate_encode(struct pri *ctrl, struct q931_call *call, static int rose_mwi_indicate_encode(struct pri *ctrl, struct q931_call *call,
const struct pri_party_id *mailbox, int basic_service, int num_messages, const struct pri_party_id *vm_id, int basic_service, int num_messages,
const struct pri_party_id *caller_id, const char *timestamp, int message_reference, const struct pri_party_id *caller_id, const char *timestamp, int message_reference,
int message_status) int message_status)
{ {
unsigned char buffer[255]; unsigned char buffer[255];
unsigned char *end; unsigned char *end;
end = enc_etsi_mwi_indicate_message(ctrl, buffer, buffer + sizeof(buffer), mailbox, end = enc_etsi_mwi_indicate_message(ctrl, buffer, buffer + sizeof(buffer), vm_id,
basic_service, num_messages, caller_id, timestamp, message_reference, basic_service, num_messages, caller_id, timestamp, message_reference,
message_status); message_status);
if (!end) { if (!end) {
@ -1843,11 +1843,13 @@ static int rose_mwi_indicate_encode(struct pri *ctrl, struct q931_call *call,
return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL); return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
} }
int pri_mwi_indicate(struct pri *ctrl, const struct pri_party_id *mailbox, int pri_mwi_indicate_v2(struct pri *ctrl, const struct pri_party_id *mailbox,
int basic_service, int num_messages, const struct pri_party_id *caller_id, const struct pri_party_id *vm_id, int basic_service, int num_messages,
const char *timestamp, int message_reference, int message_status) const struct pri_party_id *caller_id, const char *timestamp, int message_reference,
int message_status)
{ {
struct q931_call *call; struct q931_call *call;
struct q931_party_id called;
if (!ctrl) { if (!ctrl) {
return -1; return -1;
@ -1868,9 +1870,10 @@ int pri_mwi_indicate(struct pri *ctrl, const struct pri_party_id *mailbox,
return -1; return -1;
} }
if (rose_mwi_indicate_encode(ctrl, call, mailbox, basic_service, num_messages, pri_copy_party_id_to_q931(&called, mailbox);
if (rose_mwi_indicate_encode(ctrl, call, vm_id, basic_service, num_messages,
caller_id, timestamp, message_reference, message_status) caller_id, timestamp, message_reference, message_status)
|| q931_facility(ctrl, call)) { || q931_facility_called(ctrl, call, &called)) {
pri_message(ctrl, pri_message(ctrl,
"Could not schedule facility message for MWI indicate message.\n"); "Could not schedule facility message for MWI indicate message.\n");
return -1; return -1;
@ -1878,6 +1881,14 @@ int pri_mwi_indicate(struct pri *ctrl, const struct pri_party_id *mailbox,
return 0; return 0;
} }
int pri_mwi_indicate(struct pri *ctrl, const struct pri_party_id *mailbox,
int basic_service, int num_messages, const struct pri_party_id *caller_id,
const char *timestamp, int message_reference, int message_status)
{
return pri_mwi_indicate_v2(ctrl, mailbox, mailbox, basic_service, num_messages,
caller_id, timestamp, message_reference, message_status);
}
/* End MWI */ /* End MWI */
/* EECT functions */ /* EECT functions */

View File

@ -980,6 +980,7 @@ 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_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); int q931_facility_display_name(struct pri *ctrl, struct q931_call *call, const struct q931_party_name *name);
int q931_facility_called(struct pri *ctrl, struct q931_call *call, const struct q931_party_id *called);
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);

53
q931.c
View File

@ -2342,12 +2342,21 @@ static int receive_called_party_number(int full_ie, struct pri *ctrl, q931_call
return -1; return -1;
} }
call->called.number.valid = 1; switch (msgtype) {
call->called.number.plan = ie->data[0] & 0x7f; case Q931_FACILITY:
if (msgtype == Q931_SETUP) { if (!q931_is_dummy_call(call)) {
/* Discard the number. */
return 0;
}
/* Fall through */
case Q931_REGISTER:
/* Accept the number for REGISTER only because it is so similar to SETUP. */
case Q931_SETUP:
q931_get_number((unsigned char *) call->called.number.str, q931_get_number((unsigned char *) call->called.number.str,
sizeof(call->called.number.str), ie->data + 1, len - 3); sizeof(call->called.number.str), ie->data + 1, len - 3);
} else if (call->ourcallstate == Q931_CALL_STATE_OVERLAP_RECEIVING) { break;
case Q931_INFORMATION:
if (call->ourcallstate == Q931_CALL_STATE_OVERLAP_RECEIVING) {
/* /*
* Since we are receiving overlap digits now, we need to append * Since we are receiving overlap digits now, we need to append
* them to any previously received digits in call->called.number.str. * them to any previously received digits in call->called.number.str.
@ -2362,6 +2371,13 @@ static int receive_called_party_number(int full_ie, struct pri *ctrl, q931_call
} }
strncat(called_end, (char *) ie->data + 1, called_len); strncat(called_end, (char *) ie->data + 1, called_len);
} }
break;
default:
/* Discard the number. */
return 0;
}
call->called.number.valid = 1;
call->called.number.plan = ie->data[0] & 0x7f;
q931_get_number((unsigned char *) call->overlap_digits, sizeof(call->overlap_digits), q931_get_number((unsigned char *) call->overlap_digits, sizeof(call->overlap_digits),
ie->data + 1, len - 3); ie->data + 1, len - 3);
@ -5103,6 +5119,35 @@ int q931_facility(struct pri *ctrl, struct q931_call *call)
return send_message(ctrl, call, Q931_FACILITY, facility_ies); return send_message(ctrl, call, Q931_FACILITY, facility_ies);
} }
/*!
* \brief Send a FACILITY message with the called party number and subaddress ies.
*
* \param ctrl D channel controller.
* \param call Call leg to send message over.
* \param called Called party information to send.
*
* \note
* This function can only be used by the dummy call because the call's called
* structure is used by normal calls to contain persistent information.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int q931_facility_called(struct pri *ctrl, struct q931_call *call, const struct q931_party_id *called)
{
static int facility_called_ies[] = {
Q931_IE_FACILITY,
Q931_CALLED_PARTY_NUMBER,
Q931_CALLED_PARTY_SUBADDR,
-1
};
q931_party_id_copy_to_address(&call->called, called);
libpri_copy_string(call->overlap_digits, call->called.number.str,
sizeof(call->overlap_digits));
return send_message(ctrl, call, Q931_FACILITY, facility_called_ies);
}
int q931_facility_display_name(struct pri *ctrl, struct q931_call *call, const struct q931_party_name *name) int q931_facility_display_name(struct pri *ctrl, struct q931_call *call, const struct q931_party_name *name)
{ {
int status; int status;