diff --git a/libpri.h b/libpri.h index 3ee78b8..2dc9a4f 100644 --- a/libpri.h +++ b/libpri.h @@ -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. * * \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 num_messages NumberOfMessages (-1 if not present). - * \param caller_id Controlling party privided number (NULL if not present). - * \param timestamp Generalized Time format (NULL 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). * @@ -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, 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 */ int pri_set_service_message_support(struct pri *pri, int supportflag); diff --git a/pri_facility.c b/pri_facility.c index c5aaa6d..656574c 100644 --- a/pri_facility.c +++ b/pri_facility.c @@ -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 pos Starting position to encode the facility ie contents. * \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 num_messages NumberOfMessages (-1 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_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. */ 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 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.invoke_id = get_invokeid(ctrl); - if (mailbox && mailbox->number.valid) { - pri_copy_party_number_to_q931(&number, &mailbox->number); + if (vm_id && vm_id->number.valid) { + pri_copy_party_number_to_q931(&number, &vm_id->number); q931_copy_number_to_rose(ctrl, &msg.args.etsi.MWIIndicate.controlling_user_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 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 num_messages NumberOfMessages (-1 if not present). - * \param caller_id Controlling party privided number (NULL if not present). - * \param timestamp Generalized Time format (NULL 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). * @@ -1826,14 +1826,14 @@ static unsigned char *enc_etsi_mwi_indicate_message(struct pri *ctrl, unsigned c * \retval -1 on error. */ 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, int message_status) { unsigned char buffer[255]; 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, message_status); 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); } -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) +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) { struct q931_call *call; + struct q931_party_id called; if (!ctrl) { return -1; @@ -1868,9 +1870,10 @@ int pri_mwi_indicate(struct pri *ctrl, const struct pri_party_id *mailbox, 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) - || q931_facility(ctrl, call)) { + || q931_facility_called(ctrl, call, &called)) { pri_message(ctrl, "Could not schedule facility message for MWI indicate message.\n"); return -1; @@ -1878,6 +1881,14 @@ int pri_mwi_indicate(struct pri *ctrl, const struct pri_party_id *mailbox, 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 */ /* EECT functions */ diff --git a/pri_internal.h b/pri_internal.h index 615c000..bc74162 100644 --- a/pri_internal.h +++ b/pri_internal.h @@ -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_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 *msg2str(int msg); diff --git a/q931.c b/q931.c index 062d618..82acfe1 100644 --- a/q931.c +++ b/q931.c @@ -2342,26 +2342,42 @@ static int receive_called_party_number(int full_ie, struct pri *ctrl, q931_call return -1; } - call->called.number.valid = 1; - call->called.number.plan = ie->data[0] & 0x7f; - if (msgtype == Q931_SETUP) { + switch (msgtype) { + case Q931_FACILITY: + 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, sizeof(call->called.number.str), ie->data + 1, len - 3); - } else if (call->ourcallstate == Q931_CALL_STATE_OVERLAP_RECEIVING) { - /* - * Since we are receiving overlap digits now, we need to append - * them to any previously received digits in call->called.number.str. - */ - called_len = strlen(call->called.number.str); - called_end = call->called.number.str + called_len; - max_len = (sizeof(call->called.number.str) - 1) - called_len; - if (max_len < len - 3) { - called_len = max_len; - } else { - called_len = len - 3; + break; + case Q931_INFORMATION: + if (call->ourcallstate == Q931_CALL_STATE_OVERLAP_RECEIVING) { + /* + * Since we are receiving overlap digits now, we need to append + * them to any previously received digits in call->called.number.str. + */ + called_len = strlen(call->called.number.str); + called_end = call->called.number.str + called_len; + max_len = (sizeof(call->called.number.str) - 1) - called_len; + if (max_len < len - 3) { + called_len = max_len; + } else { + called_len = len - 3; + } + 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), 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); } +/*! + * \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 status;