Make PTP DivertingLegInformation3 message behavior closer to the specifications.
authorRichard Mudgett <rmudgett@digium.com>
Mon, 27 Apr 2009 20:03:49 +0000 (20:03 +0000)
committerRichard Mudgett <rmudgett@digium.com>
Mon, 27 Apr 2009 20:03:49 +0000 (20:03 +0000)
*  Wait for a DivertingLegInformation3 message after receiving a
DivertingLegInformation1 message to complete the redirecting-to information
before queuing a redirecting update to the other channel.

*  A DivertingLegInformation2 message should be responded to with a
DivertingLegInformation3 when the COLR is determined.  If the call
could or does experience another redirection, you should manually
determine the COLR to send to the switch by setting REDIRECTING(to-pres)
to the COLR and setting REDIRECTING(to-num) = ${EXTEN}.

*  A DivertingLegInformation2 message must have an original called number
if the redirection count is greater than one.  Since Asterisk does
not keep track of this information, we can only indicate that the
number is not available due to interworking.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@190735 65c4cc65-6c06-0410-ace0-fbb531ad65f3

CHANGES
channels/chan_misdn.c
channels/misdn/isdn_lib.c
channels/misdn/isdn_lib.h
funcs/func_redirecting.c

diff --git a/CHANGES b/CHANGES
index 2c70d61..bb9239e 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -72,6 +72,11 @@ mISDN channel driver (chan_misdn) changes
     the CCBS/CCNR functionality.
   * Added new dialplan function mISDN_CC which permits retrieval of various
     values from an active call completion record.
+  * For PTP, you should manually send the COLR for an incomming redirected
+    call if the incoming call could or does experience further redirects.
+    Just set the REDIRECTING(to-num,i) = ${EXTEN} and set the
+    REDIRECTING(to-pres) to the COLR.  A call has been redirected if the
+    REDIRECTING(from-num) is not empty.
 
 thirdparty mISDN enhancements
 -----------------------------
index f743ec8..63b3271 100644 (file)
@@ -316,7 +316,9 @@ enum misdn_chan_state {
        MISDN_HOLD_DISCONNECT,     /*!< when on hold */
 };
 
+/*! Asterisk created the channel (outgoing call) */
 #define ORG_AST 1
+/*! mISDN created the channel (incoming call) */
 #define ORG_MISDN 2
 
 struct hold_info {
@@ -6155,33 +6157,45 @@ static void misdn_copy_redirecting_to_ast(struct ast_channel *ast, const struct
  *
  * \param ast Current Asterisk channel
  * \param bc Associated B channel
+ * \param originator Who originally created this channel. ORG_AST or ORG_MISDN
  *
  * \return Nothing
  */
-static void misdn_update_redirecting(struct ast_channel *ast, struct misdn_bchannel *bc)
+static void misdn_update_redirecting(struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
 {
-       int Is_PTMP;
+       int is_ptmp;
 
        misdn_copy_redirecting_from_ast(bc, ast);
 
-       Is_PTMP = !misdn_lib_is_ptp(bc->port);
-       if (Is_PTMP) {
+       if (originator != ORG_MISDN) {
+               return;
+       }
+
+       is_ptmp = !misdn_lib_is_ptp(bc->port);
+       if (is_ptmp) {
                /* Send NOTIFY(call-is-diverting, redirecting.to data) */
                bc->redirecting.to_changed = 1;
                bc->notify_description_code = mISDN_NOTIFY_CODE_CALL_IS_DIVERTING;
                misdn_lib_send_event(bc, EVENT_NOTIFY);
 #if defined(AST_MISDN_ENHANCEMENTS)
        } else {
-               /* Send DivertingLegInformation1 */
-               bc->fac_out.Function = Fac_DivertingLegInformation1;
-               bc->fac_out.u.DivertingLegInformation1.InvokeID = ++misdn_invoke_id;
-               bc->fac_out.u.DivertingLegInformation1.DiversionReason =
-                       misdn_to_diversion_reason(bc->redirecting.reason);
-               bc->fac_out.u.DivertingLegInformation1.SubscriptionOption = 2;/* notificationWithDivertedToNr */
-               bc->fac_out.u.DivertingLegInformation1.DivertedToPresent = 1;
-               misdn_PresentedNumberUnscreened_fill(&bc->fac_out.u.DivertingLegInformation1.DivertedTo, &bc->redirecting.to);
-               print_facility(&bc->fac_out, bc);
-               misdn_lib_send_event(bc, EVENT_FACILITY);
+               int match;      /* TRUE if the dialed number matches the redirecting to number */
+
+               match = (strcmp(ast->exten, bc->redirecting.to.number) == 0) ? 1 : 0;
+               if (!bc->div_leg_3_tx_pending
+                       || !match) {
+                       /* Send DivertingLegInformation1 */
+                       bc->fac_out.Function = Fac_DivertingLegInformation1;
+                       bc->fac_out.u.DivertingLegInformation1.InvokeID = ++misdn_invoke_id;
+                       bc->fac_out.u.DivertingLegInformation1.DiversionReason =
+                               misdn_to_diversion_reason(bc->redirecting.reason);
+                       bc->fac_out.u.DivertingLegInformation1.SubscriptionOption = 2;/* notificationWithDivertedToNr */
+                       bc->fac_out.u.DivertingLegInformation1.DivertedToPresent = 1;
+                       misdn_PresentedNumberUnscreened_fill(&bc->fac_out.u.DivertingLegInformation1.DivertedTo, &bc->redirecting.to);
+                       print_facility(&bc->fac_out, bc);
+                       misdn_lib_send_event(bc, EVENT_FACILITY);
+               }
+               bc->div_leg_3_tx_pending = 0;
 
                /* Send DivertingLegInformation3 */
                bc->fac_out.Function = Fac_DivertingLegInformation3;
@@ -6368,6 +6382,10 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
                                &newbc->fac_out.u.DivertingLegInformation2.Diverting,
                                &newbc->redirecting.from);
                        newbc->fac_out.u.DivertingLegInformation2.OriginalCalledPresent = 0;
+                       if (1 < newbc->redirecting.count) {
+                               newbc->fac_out.u.DivertingLegInformation2.OriginalCalledPresent = 1;
+                               newbc->fac_out.u.DivertingLegInformation2.OriginalCalled.Type = 2;/* numberNotAvailableDueToInterworking */
+                       }
                }
 #endif /* defined(AST_MISDN_ENHANCEMENTS) */
 
@@ -6488,6 +6506,18 @@ static int misdn_answer(struct ast_channel *ast)
                p->bc->connected.number_plan = p->bc->dialed.number_plan;
        }
 
+#if defined(AST_MISDN_ENHANCEMENTS)
+       if (p->bc->div_leg_3_tx_pending) {
+               p->bc->div_leg_3_tx_pending = 0;
+
+               /* Send DivertingLegInformation3 */
+               p->bc->fac_out.Function = Fac_DivertingLegInformation3;
+               p->bc->fac_out.u.DivertingLegInformation3.InvokeID = ++misdn_invoke_id;
+               p->bc->fac_out.u.DivertingLegInformation3.PresentationAllowedIndicator =
+                       (p->bc->connected.presentation == 0) ? 1 : 0;
+               print_facility(&p->bc->fac_out, p->bc);
+       }
+#endif /* defined(AST_MISDN_ENHANCEMENTS) */
        misdn_lib_send_event(p->bc, EVENT_CONNECT);
        start_bc_tones(p);
 
@@ -6690,7 +6720,7 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data,
                break;
        case AST_CONTROL_REDIRECTING:
                chan_misdn_log(1, p->bc->port, "* IND :\tredirecting info update pid:%d\n", p->bc->pid);
-               misdn_update_redirecting(ast, p->bc);
+               misdn_update_redirecting(ast, p->bc, p->originator);
                break;
        default:
                chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc->pid);
@@ -8608,6 +8638,7 @@ static void misdn_facility_ie_handler(enum event_e event, struct misdn_bchannel
 #endif /* We don't handle this yet */
        case Fac_DivertingLegInformation1:
                /* Private-Public ISDN interworking message */
+               bc->div_leg_3_rx_wanted = 0;
                if (ch && ch->ast) {
                        bc->redirecting.reason =
                                diversion_reason_to_misdn(bc->fac_in.u.DivertingLegInformation1.DiversionReason);
@@ -8618,12 +8649,15 @@ static void misdn_facility_ie_handler(enum event_e event, struct misdn_bchannel
                                /* Add configured prefix to redirecting.to.number */
                                misdn_add_number_prefix(bc->port, bc->redirecting.to.number_type,
                                        bc->redirecting.to.number, sizeof(bc->redirecting.to.number));
-
-                               misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting);
-                               ast_channel_queue_redirecting_update(ch->ast, &ch->ast->redirecting);
                        } else {
-                               ch->ast->redirecting.reason = misdn_to_ast_reason(bc->redirecting.reason);
+                               bc->redirecting.to.number[0] = '\0';
+                               bc->redirecting.to.number_plan = NUMPLAN_ISDN;
+                               bc->redirecting.to.number_type = NUMTYPE_UNKNOWN;
+                               bc->redirecting.to.presentation = 1;/* restricted */
+                               bc->redirecting.to.screening = 0;/* unscreened */
                        }
+                       misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting);
+                       bc->div_leg_3_rx_wanted = 1;
                }
                break;
        case Fac_DivertingLegInformation2:
@@ -8631,7 +8665,25 @@ static void misdn_facility_ie_handler(enum event_e event, struct misdn_bchannel
                switch (event) {
                case EVENT_SETUP:
                        /* Comes in on a SETUP with redirecting.from information */
+                       bc->div_leg_3_tx_pending = 1;
                        if (ch && ch->ast) {
+                               /*
+                                * Setup the redirecting.to informtion so we can identify
+                                * if the user wants to manually supply the COLR for this
+                                * redirected to number if further redirects could happen.
+                                *
+                                * All the user needs to do is set the REDIRECTING(to-pres)
+                                * to the COLR and REDIRECTING(to-num) = ${EXTEN} to be safe
+                                * after determining that the incoming call was redirected by
+                                * checking if there is a REDIRECTING(from-num).
+                                */
+                               ast_copy_string(bc->redirecting.to.number, bc->dialed.number,
+                                       sizeof(bc->redirecting.to.number));
+                               bc->redirecting.to.number_plan = bc->dialed.number_plan;
+                               bc->redirecting.to.number_type = bc->dialed.number_type;
+                               bc->redirecting.to.presentation = 1;/* restricted */
+                               bc->redirecting.to.screening = 0;/* unscreened */
+
                                bc->redirecting.reason =
                                        diversion_reason_to_misdn(bc->fac_in.u.DivertingLegInformation2.DiversionReason);
                                bc->redirecting.count = bc->fac_in.u.DivertingLegInformation2.DiversionCounter;
@@ -8660,7 +8712,17 @@ static void misdn_facility_ie_handler(enum event_e event, struct misdn_bchannel
                break;
        case Fac_DivertingLegInformation3:
                /* Private-Public ISDN interworking message */
-               /* Don't know what to do with this. */
+               if (bc->div_leg_3_rx_wanted) {
+                       bc->div_leg_3_rx_wanted = 0;
+
+                       if (ch && ch->ast) {
+                               ch->ast->redirecting.to.number_presentation =
+                                       bc->fac_in.u.DivertingLegInformation3.PresentationAllowedIndicator
+                                       ? AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_UNSCREENED
+                                       : AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED;
+                               ast_channel_queue_redirecting_update(ch->ast, &ch->ast->redirecting);
+                       }
+               }
                break;
 
 #else  /* !defined(AST_MISDN_ENHANCEMENTS) */
@@ -9786,6 +9848,17 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
                if (bc->fac_in.Function != Fac_None) {
                        misdn_facility_ie_handler(event, bc, ch);
                }
+#if defined(AST_MISDN_ENHANCEMENTS)
+               if (bc->div_leg_3_rx_wanted) {
+                       bc->div_leg_3_rx_wanted = 0;
+
+                       if (ch->ast) {
+                               ch->ast->redirecting.to.number_presentation =
+                                       AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED;
+                               ast_channel_queue_redirecting_update(ch->ast, &ch->ast->redirecting);
+                       }
+               }
+#endif /* defined(AST_MISDN_ENHANCEMENTS) */
 
                /* we answer when we've got our very new L3 ID from the NT stack */
                misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
index 4a0da06..c0a4170 100644 (file)
@@ -764,6 +764,11 @@ static void empty_bc(struct misdn_bchannel *bc)
        bc->progress_location=0;
        bc->progress_indicator=0;
 
+#if defined(AST_MISDN_ENHANCEMENTS)
+       bc->div_leg_3_rx_wanted = 0;
+       bc->div_leg_3_tx_pending = 0;
+#endif /* defined(AST_MISDN_ENHANCEMENTS) */
+
 /** Set Default Bearer Caps **/
        bc->capability=INFO_CAPABILITY_SPEECH;
        bc->law=INFO_CODEC_ALAW;
index 7bd5165..df11659 100644 (file)
@@ -493,6 +493,18 @@ struct misdn_bchannel {
         */
        int progress_indicator;
 
+#if defined(AST_MISDN_ENHANCEMENTS)
+       /*!
+        * \brief TRUE if waiting for DivertingLegInformation3 to queue redirecting update.
+        */
+       int div_leg_3_rx_wanted;
+
+       /*!
+        * \brief TRUE if a DivertingLegInformation3 needs to be sent with CONNECT.
+        */
+       int div_leg_3_tx_pending;
+#endif /* defined(AST_MISDN_ENHANCEMENTS) */
+
        /*! \brief Inbound FACILITY message function type and contents */
        struct FacParm fac_in;
 
index 4a2d7be..62c6d7b 100644 (file)
@@ -49,6 +49,13 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/options.h"
 #include "asterisk/callerid.h"
 
+/*
+ * Do not document the REDIRECTING(pres) datatype.
+ * It has turned out that the from-pres and to-pres values must be kept
+ * separate.  They represent two different parties and there is a case when
+ * they are active at the same time.  The plain pres option will simply
+ * live on as a historical relic.
+ */
 /*** DOCUMENTATION
        <function name="REDIRECTING" language="en_US">
                <synopsis>
@@ -62,11 +69,12 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
                                        <enum name = "from-num" />
                                        <enum name = "from-name" />
                                        <enum name = "from-ton" />
+                                       <enum name = "from-pres" />
                                        <enum name = "to-all" />
                                        <enum name = "to-num" />
                                        <enum name = "to-name" />
                                        <enum name = "to-ton" />
-                                       <enum name = "pres" />
+                                       <enum name = "to-pres" />
                                        <enum name = "reason" />
                                        <enum name = "count" />
                                </enumlist>
@@ -323,7 +331,7 @@ static int redirecting_write(struct ast_channel *chan, const char *cmd, char *da
                case 'i':
                        set_it = ast_channel_set_redirecting;
                        break;
-               
+
                default:
                        ast_log(LOG_ERROR, "Unknown redirecting option '%s'.\n", option);
                        return 0;