[Asterisk-code-review] sig_analog: Add Called Subscriber Held capability. (asterisk[master])

N A asteriskteam at digium.com
Thu Dec 22 09:13:00 CST 2022


N A has uploaded this change for review. ( https://gerrit.asterisk.org/c/asterisk/+/19747 )


Change subject: sig_analog: Add Called Subscriber Held capability.
......................................................................

sig_analog: Add Called Subscriber Held capability.

This adds support for Called Subscriber Held for FXS
lines, which allows users to go on hook when receiving
a call and resume the call later from another phone on
the same line, without disconnecting the call. This is
a convenience mechanism that most real PSTN telephone
switches support.

ASTERISK-30372 #close

Change-Id: Iaac4384f73bd0f354d01b1f53e168b385dcbdbd4
---
M channels/chan_dahdi.c
M channels/chan_dahdi.h
M channels/sig_analog.c
M channels/sig_analog.h
M configs/samples/chan_dahdi.conf.sample
A doc/CHANGES-staging/csh.txt
6 files changed, 84 insertions(+), 0 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/47/19747/1

diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 5607eb0..ffb9aa8 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -12806,6 +12806,7 @@
 		tmp->usedistinctiveringdetection = usedistinctiveringdetection;
 		tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
 		tmp->threewaycalling = conf->chan.threewaycalling;
+		tmp->calledsubscriberheld = conf->chan.calledsubscriberheld; /* Not used in chan_dahdi.c, just analog pvt, but must exist on the DAHDI pvt anyways */
 		tmp->adsi = conf->chan.adsi;
 		tmp->use_smdi = conf->chan.use_smdi;
 		tmp->permhidecallerid = conf->chan.hidecallerid;
@@ -13103,6 +13104,7 @@
 				analog_p->ani_wink_time = conf->chan.ani_wink_time;
 				analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
 				analog_p->permcallwaiting = conf->chan.callwaiting; /* permcallwaiting possibly modified in analog_config_complete */
+				analog_p->calledsubscriberheld = conf->chan.calledsubscriberheld; /* Only actual used in analog pvt, not DAHDI pvt */
 				analog_p->callreturn = conf->chan.callreturn;
 				analog_p->cancallforward = conf->chan.cancallforward;
 				analog_p->canpark = conf->chan.canpark;
@@ -18192,6 +18194,8 @@
 			confp->chan.busycount = atoi(v->value);
 		} else if (!strcasecmp(v->name, "busypattern")) {
 			parse_busy_pattern(v, &confp->chan.busy_cadence);
+		} else if (!strcasecmp(v->name, "calledsubscriberheld")) {
+			confp->chan.calledsubscriberheld = ast_true(v->value);
 		} else if (!strcasecmp(v->name, "callprogress")) {
 			confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
 			if (ast_true(v->value))
diff --git a/channels/chan_dahdi.h b/channels/chan_dahdi.h
index de813f2..170da0e 100644
--- a/channels/chan_dahdi.h
+++ b/channels/chan_dahdi.h
@@ -204,6 +204,13 @@
 	 */
 	unsigned int busydetect:1;
 	/*!
+	 * \brief TRUE if Called Subscriber held is enabled.
+	 * This allows a single incoming call to hold a DAHDI channel up,
+	 * allowing a recipient to hang up an extension and pick up another
+	 * phone on the same line without disconnecting the call.
+	 */
+	unsigned int calledsubscriberheld:1;
+	/*!
 	 * \brief TRUE if call return is enabled.
 	 * (*69, if your dialplan doesn't catch this first)
 	 * \note Set from the "callreturn" value read in from chan_dahdi.conf
diff --git a/channels/sig_analog.c b/channels/sig_analog.c
index b694a96..d77b0c4 100644
--- a/channels/sig_analog.c
+++ b/channels/sig_analog.c
@@ -805,6 +805,11 @@
 		return 0;
 	}
 
+	/* If line is being held, definitely not (don't allow call waitings to an on-hook phone) */
+	if (p->cshactive) {
+		return 0;
+	}
+
 	/* If no owner definitely available */
 	if (!p->owner) {
 		offhook = analog_is_off_hook(p);
@@ -2892,6 +2897,34 @@
 		analog_get_and_handle_alarms(p);
 		cause_code->ast_cause = AST_CAUSE_NETWORK_OUT_OF_ORDER;
 	case ANALOG_EVENT_ONHOOK:
+		if (p->calledsubscriberheld && (p->sig == ANALOG_SIG_FXOLS || p->sig == ANALOG_SIG_FXOGS || p->sig == ANALOG_SIG_FXOKS) && idx == ANALOG_SUB_REAL) {
+			ast_debug(4, "Channel state on %s is %d\n", ast_channel_name(ast), ast_channel_state(ast));
+			/* Called Subscriber Held: don't let the called party hang up on an incoming call immediately (if it's the only call). */
+			if (p->subs[ANALOG_SUB_CALLWAIT].owner || p->subs[ANALOG_SUB_THREEWAY].owner) {
+				ast_debug(2, "Letting this call hang up normally, since it's not the only call\n");
+			} else if (!p->owner || !p->subs[ANALOG_SUB_REAL].owner || ast_channel_state(ast) != AST_STATE_UP) {
+				ast_debug(2, "Called Subscriber Held does not apply: channel state is %d\n", ast_channel_state(ast));
+			} else if (!p->owner || !p->subs[ANALOG_SUB_REAL].owner || strcmp(ast_channel_appl(p->subs[ANALOG_SUB_REAL].owner), "AppDial")) {
+				/* Called Subscriber held only applies to incoming calls, not outgoing calls.
+				 * We can't use p->outgoing because that is always true, for both incoming and outgoing calls, so it's not accurate.
+				 * We can check the channel application/data instead.
+				 * For incoming calls to the channel, it will look like: AppDial / (Outgoing Line)
+				 * We only want this behavior for regular calls anyways (and not, say, Queue),
+				 * so this would actually work great. But accessing ast_channel_appl can cause a crash if there are no calls left,
+				 * so this check must occur AFTER we confirm the channel state *is* still UP.
+				 */
+				ast_debug(2, "Called Subscriber Held does not apply: not an incoming call\n");
+			} else if (analog_is_off_hook(p)) {
+				ast_log(LOG_WARNING, "Got ONHOOK but channel %d is off hook?\n", p->channel); /* Shouldn't happen */
+			} else {
+				ast_verb(3, "Holding incoming call %s for channel %d\n", ast_channel_name(ast), p->channel);
+				/* Inhibit dahdi_hangup from getting called, and do nothing else now.
+				 * When the DAHDI channel goes off hook again, it'll just get reconnected with the incoming call,
+				 * to which, as far as its concerned, nothing has happened. */
+				p->cshactive = 1; /* Keep track that this DAHDI channel is currently being held by an incoming call. */
+				break;
+			}
+		}
 		ast_queue_control_data(ast, AST_CONTROL_PVT_CAUSE_CODE, cause_code, data_size);
 		ast_channel_hangupcause_hash_set(ast, cause_code, data_size);
 		switch (p->sig) {
@@ -3768,6 +3801,7 @@
 		case ANALOG_SIG_FXOKS:
 			res = analog_off_hook(i);
 			i->fxsoffhookstate = 1;
+			i->cshactive = 0;
 			if (res && (errno == EBUSY)) {
 				break;
 			}
diff --git a/channels/sig_analog.h b/channels/sig_analog.h
index 7e9acda..f332d4f 100644
--- a/channels/sig_analog.h
+++ b/channels/sig_analog.h
@@ -282,6 +282,7 @@
 	unsigned int ani_wink_time:16;			/* Safe wait time before we wink to start ANI spill */
 
 	unsigned int answeronpolarityswitch:1;
+	unsigned int calledsubscriberheld:1;	/*!< TRUE if a single incoming call can hold an FXS channel */
 	unsigned int callreturn:1;
 	unsigned int cancallforward:1;
 	unsigned int canpark:1;
@@ -320,6 +321,7 @@
 
 	/* XXX: All variables after this are internal */
 	unsigned int callwaiting:1;		/*!< TRUE if call waiting is enabled. (Active option) */
+	unsigned int cshactive:1;		/*!< TRUE if FXS channel is currently held by an incoming call */
 	unsigned int dialednone:1;
 	unsigned int dialing:1;			/*!< TRUE if in the process of dialing digits or sending something */
 	unsigned int dnd:1;				/*!< TRUE if Do-Not-Disturb is enabled. */
diff --git a/configs/samples/chan_dahdi.conf.sample b/configs/samples/chan_dahdi.conf.sample
index 6b29549..c01465e 100644
--- a/configs/samples/chan_dahdi.conf.sample
+++ b/configs/samples/chan_dahdi.conf.sample
@@ -746,6 +746,18 @@
 ;
 callwaitingcallerid=yes
 ;
+; Whether or not to allow users to go on-hook when receiving an incoming call
+; without disconnecting it. Users can later resume the call from any phone
+; on the same physical phone line (the same DAHDI channel).
+; This setting only has an effect on FXS (FXO-signalled) channels where there
+; is only a single incoming call to the DAHDI channel, using the Dial application.
+; (This is a convenience mechanism to avoid users wishing to resume a conversation
+; at a different phone from leaving a phone off the hook, resuming elsewhere,
+; and forgetting to restore the original phone on hook afterwards.)
+; Default is no.
+;
+;calledsubscriberheld=yes
+;
 ; Support three-way calling
 ;
 threewaycalling=yes
diff --git a/doc/CHANGES-staging/csh.txt b/doc/CHANGES-staging/csh.txt
new file mode 100644
index 0000000..c16b207
--- /dev/null
+++ b/doc/CHANGES-staging/csh.txt
@@ -0,0 +1,7 @@
+Subject: sig_analog
+
+Called Subscriber Held is now supported for analog FXS
+channels, using the calledsubscriberheld option. This
+allows a station user to go on hook when receiving an
+incoming call and resume from another phone on the same
+line by going on hook, without disconnecting the call.

-- 
To view, visit https://gerrit.asterisk.org/c/asterisk/+/19747
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Change-Id: Iaac4384f73bd0f354d01b1f53e168b385dcbdbd4
Gerrit-Change-Number: 19747
Gerrit-PatchSet: 1
Gerrit-Owner: N A <asterisk at phreaknet.org>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20221222/f25a07d9/attachment-0001.html>


More information about the asterisk-code-review mailing list