diff options
-rw-r--r-- | CHANGES | 5 | ||||
-rw-r--r-- | channels/chan_misdn.c | 113 | ||||
-rw-r--r-- | channels/misdn/isdn_lib.c | 5 | ||||
-rw-r--r-- | channels/misdn/isdn_lib.h | 12 | ||||
-rw-r--r-- | funcs/func_redirecting.c | 12 |
5 files changed, 125 insertions, 22 deletions
@@ -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 ----------------------------- diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c index f743ec8d1..63b3271fc 100644 --- a/channels/chan_misdn.c +++ b/channels/chan_misdn.c @@ -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); diff --git a/channels/misdn/isdn_lib.c b/channels/misdn/isdn_lib.c index 4a0da06d3..c0a4170e2 100644 --- a/channels/misdn/isdn_lib.c +++ b/channels/misdn/isdn_lib.c @@ -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; diff --git a/channels/misdn/isdn_lib.h b/channels/misdn/isdn_lib.h index 7bd516565..df11659c3 100644 --- a/channels/misdn/isdn_lib.h +++ b/channels/misdn/isdn_lib.h @@ -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; diff --git a/funcs/func_redirecting.c b/funcs/func_redirecting.c index 4a2d7be26..62c6d7bc9 100644 --- a/funcs/func_redirecting.c +++ b/funcs/func_redirecting.c @@ -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; |