From b9397c75415c25cbaf0140ae0c7c0cedc1c62c3b Mon Sep 17 00:00:00 2001 From: Richard Mudgett Date: Fri, 20 Nov 2009 23:42:40 +0000 Subject: [PATCH] Delay processing of facility ie's after all other ie's are processed. * Some ROSE message processing depends on the presence of other ies. The DivertingLegInformation1, and 3 messages will be used as the default connected line number if the connected number ie is not present. The redirecting number ie is used as a default to the redirecting number in the DivertingLegInformation2 message if the ROSE message does not contain it and the redirecting number ie is present. * Some ROSE message processing depends upon other ie values. The StatusRequest, CCBS-T-Call, and CcRingout messages collectively need the BC, HLC, LLC, called number, called subaddress, calling number, and calling subaddress ie information to be available. git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1345 2fbb986a-6c06-0410-b554-c9c1f0a7f128 --- pri_facility.c | 73 ++++++++++++++++++++++++++------------------------ pri_internal.h | 17 ++++++++++++ q931.c | 45 +++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 35 deletions(-) diff --git a/pri_facility.c b/pri_facility.c index fa34e3c..9a8e2ce 100644 --- a/pri_facility.c +++ b/pri_facility.c @@ -3555,27 +3555,31 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie break; #endif /* Not handled yet */ case ROSE_ETSI_DivertingLegInformation1: - /* - * Unless otherwise indicated by CONNECT, the divertedToNumber will be - * the remote_id.number. - * - * Fortunately, the connected number ie is supposed to come after the - * facility ie in the same message so it will be processed later. - */ if (invoke->args.etsi.DivertingLegInformation1.diverted_to_present) { - rose_copy_presented_number_unscreened_to_q931(ctrl, &call->remote_id.number, + rose_copy_presented_number_unscreened_to_q931(ctrl, &party_id.number, &invoke->args.etsi.DivertingLegInformation1.diverted_to); /* * We set the presentation value since the sender cannot know the * presentation value preference of the destination party. */ - if (call->remote_id.number.str[0]) { - call->remote_id.number.presentation = + if (party_id.number.str[0]) { + party_id.number.presentation = PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED; + } else { + party_id.number.presentation = + PRI_PRES_UNAVAILABLE | PRI_PRES_USER_NUMBER_UNSCREENED; } } else { - q931_party_number_init(&call->remote_id.number); - call->remote_id.number.valid = 1; + q931_party_number_init(&party_id.number); + party_id.number.valid = 1; + } + + /* + * Unless otherwise indicated by CONNECT, the divertedToNumber will be + * the remote_id.number. + */ + if (!call->connected_number_in_message) { + call->remote_id.number = party_id.number; } /* divertedToNumber is put in redirecting.to.number */ @@ -3589,7 +3593,7 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED; break; case 2: /* notificationWithDivertedToNr */ - call->redirecting.to.number = call->remote_id.number; + call->redirecting.to.number = party_id.number; break; } @@ -3616,7 +3620,7 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie rose_copy_presented_number_unscreened_to_q931(ctrl, &call->redirecting.from.number, &invoke->args.etsi.DivertingLegInformation2.diverting); - } else { + } else if (!call->redirecting_number_in_message) { q931_party_number_init(&call->redirecting.from.number); call->redirecting.from.number.valid = 1; } @@ -3636,15 +3640,14 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie /* * Unless otherwise indicated by CONNECT, this will be the * remote_id.number.presentation. - * - * Fortunately, the connected number ie is supposed to come after the - * facility ie in the same message so it will be processed later. */ if (!invoke->args.etsi.DivertingLegInformation3.presentation_allowed_indicator) { - call->remote_id.number.presentation = - PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED; call->redirecting.to.number.presentation = PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED; + if (!call->connected_number_in_message) { + call->remote_id.number.presentation = + PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED; + } } switch (call->redirecting.state) { @@ -3949,19 +3952,20 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie &deflection); break; case ROSE_QSIG_DivertingLegInformation1: + q931_party_number_init(&party_id.number); + rose_copy_number_to_q931(ctrl, &party_id.number, + &invoke->args.qsig.DivertingLegInformation1.nominated_number); + if (party_id.number.str[0]) { + party_id.number.presentation = + PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED; + } + /* * Unless otherwise indicated by CONNECT, the nominatedNr will be * the remote_id.number. - * - * Fortunately, the connected number ie is supposed to come after the - * facility ie in the same message so it will be processed later. */ - q931_party_number_init(&call->remote_id.number); - rose_copy_number_to_q931(ctrl, &call->remote_id.number, - &invoke->args.qsig.DivertingLegInformation1.nominated_number); - if (call->remote_id.number.str[0]) { - call->remote_id.number.presentation = - PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED; + if (!call->connected_number_in_message) { + call->remote_id.number = party_id.number; } /* nominatedNr is put in redirecting.to.number */ @@ -3975,7 +3979,7 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED; break; case QSIG_NOTIFICATION_WITH_DIVERTED_TO_NR: - call->redirecting.to.number = call->remote_id.number; + call->redirecting.to.number = party_id.number; break; } @@ -4002,7 +4006,7 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie rose_copy_presented_number_unscreened_to_q931(ctrl, &call->redirecting.from.number, &invoke->args.qsig.DivertingLegInformation2.diverting); - } else { + } else if (!call->redirecting_number_in_message) { q931_party_number_init(&call->redirecting.from.number); call->redirecting.from.number.valid = 1; } @@ -4042,15 +4046,14 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie /* * Unless otherwise indicated by CONNECT, this will be the * remote_id.number.presentation. - * - * Fortunately, the connected number ie is supposed to come after the - * facility ie in the same message so it will be processed later. */ if (!invoke->args.qsig.DivertingLegInformation3.presentation_allowed_indicator) { - call->remote_id.number.presentation = - PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED; call->redirecting.to.number.presentation = PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED; + if (!call->connected_number_in_message) { + call->remote_id.number.presentation = + PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED; + } } /* redirectionName is put in redirecting.to.name */ diff --git a/pri_internal.h b/pri_internal.h index 7181c75..2d54cd2 100644 --- a/pri_internal.h +++ b/pri_internal.h @@ -52,6 +52,9 @@ struct pri_sched { /*! Maximum number of scheduled events active at the same time. */ #define MAX_SCHED 128 +/*! Maximum number of facility ie's to handle per incoming message. */ +#define MAX_FACILITY_IES 8 + /*! \brief D channel controller structure */ struct pri { int fd; /* File descriptor for D-Channel */ @@ -143,6 +146,16 @@ struct pri { short last_invoke; /* Last ROSE invoke ID (Valid in master record only) */ unsigned char sendfacility; + + /*! For delayed processing of facility ie's. */ + struct { + /*! Array of facility ie locations in the current received message. */ + q931_ie *ie[MAX_FACILITY_IES]; + /*! Codeset facility ie found within. */ + unsigned char codeset[MAX_FACILITY_IES]; + /*! Number of facility ie's in the array from the current received message. */ + unsigned char count; + } facility; }; /*! \brief Maximum name length plus null terminator (From ECMA-164) */ @@ -469,6 +482,10 @@ struct q931_call { int hold_timer; int deflection_in_progress; /*!< CallDeflection for NT PTMP in progress. */ + /*! TRUE if the connected number ie was in the current received message. */ + int connected_number_in_message; + /*! TRUE if the redirecting number ie was in the current received message. */ + int redirecting_number_in_message; int useruserprotocoldisc; char useruserinfo[256]; diff --git a/q931.c b/q931.c index 5b60352..165c231 100644 --- a/q931.c +++ b/q931.c @@ -1740,6 +1740,7 @@ static int receive_connected_number(int full_ie, struct pri *ctrl, q931_call *ca { int i = 0; + call->connected_number_in_message = 1; call->remote_id.number.valid = 1; call->remote_id.number.presentation = PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED; @@ -1824,6 +1825,7 @@ static int receive_redirecting_number(int full_ie, struct pri *ctrl, q931_call * { int i = 0; + call->redirecting_number_in_message = 1; call->redirecting.from.number.valid = 1; call->redirecting.from.number.presentation = PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED; @@ -2343,6 +2345,25 @@ static int transmit_facility(int full_ie, struct pri *ctrl, q931_call *call, int } static int receive_facility(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len) +{ + /* Delay processing facility ie's till after all other ie's are processed. */ + if (MAX_FACILITY_IES <= ctrl->facility.count) { + pri_message(ctrl, "!! Too many facility ie's to delay.\n"); + return -1; + } + /* Make sure we have enough room for the protocol profile ie octet(s) */ + if (ie->data + ie->len < ie->data + 2) { + return -1; + } + + /* Save the facility ie location for delayed decode. */ + ctrl->facility.ie[ctrl->facility.count] = ie; + ctrl->facility.codeset[ctrl->facility.count] = Q931_IE_CODESET((unsigned) full_ie); + ++ctrl->facility.count; + return 0; +} + +static int process_facility(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie) { struct fac_extension_header header; struct rose_message rose; @@ -2416,6 +2437,24 @@ static int receive_facility(int full_ie, struct pri *ctrl, q931_call *call, int return 0; } +static void q931_handle_facilities(struct pri *ctrl, q931_call *call, int msgtype) +{ + unsigned idx; + unsigned codeset; + unsigned full_ie; + q931_ie *ie; + + for (idx = 0; idx < ctrl->facility.count; ++idx) { + ie = ctrl->facility.ie[idx]; + if (ctrl->debug & PRI_DEBUG_Q931_STATE) { + codeset = ctrl->facility.codeset[idx]; + full_ie = Q931_FULL_IE(codeset, ie->ie); + pri_message(ctrl, "-- Delayed processing IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie)); + } + process_facility(ctrl, call, msgtype, ie); + } +} + static int transmit_progress_indicator(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len, int order) { int code, mask; @@ -5798,6 +5837,9 @@ int q931_receive(struct pri *ctrl, q931_h *h, int len) } /* Preliminary handling */ + ctrl->facility.count = 0; + c->connected_number_in_message = 0; + c->redirecting_number_in_message = 0; if ((h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) || (h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) { prepare_to_handle_maintenance_message(ctrl, mh, c); } else { @@ -5892,6 +5934,9 @@ int q931_receive(struct pri *ctrl, q931_h *h, int len) } } + /* Now handle the facility ie's after all the other ie's were processed. */ + q931_handle_facilities(ctrl, c, mh->msg); + /* Post handling */ if ((h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_1) || (h->pd == MAINTENANCE_PROTOCOL_DISCRIMINATOR_2)) { res = post_handle_maintenance_message(ctrl, h->pd, mh, c);