Hookflash can be performed by hang-up or by dialing one pulse

This allows short hookflash.
This commit is contained in:
Andreas Eversberg 2023-01-02 21:34:15 +01:00
parent 9bf05e0bdb
commit a70bff87fc
1 changed files with 69 additions and 52 deletions

View File

@ -1262,9 +1262,65 @@ static void swap_active_hold(pstn_t *pstn)
jitter_reset(&pstn->tx_dejitter);
}
/* process hookflash from various events: short hangup, off-hook-pulse, pulse digit 1 ... */
static void hookflash(pstn_t *pstn)
{
/* stop tone (CW tone) */
tone_off(pstn);
/* clear dialing */
pstn->dialing[0] = '\0';
/* if call on hold, swap calls */
if (pstn->call[PSTN_CALL_HOLD]->cc_callref) {
PDEBUG(DTEL, DEBUG_INFO, "There is a call on hold, so swap both calls.\n");
/* swap ACTIVE call and call on HOLD */
swap_active_hold(pstn);
/* send notify to call on hold */
notify_ind(pstn->call[PSTN_CALL_HOLD], OSMO_CC_NOTIFY_REMOTE_HOLD);
/* if waiting call, answer it */
if (pstn->call[PSTN_CALL_ACTIVE]->state != CALL_STATE_ACTIVE
&& pstn->call[PSTN_CALL_ACTIVE]->state != CALL_STATE_HOLD) {
/* setup confirm */
setup_cnf(pstn, PSTN_CALL_ACTIVE);
}
/* change state */
pstn_call_state(pstn->call[PSTN_CALL_ACTIVE], CALL_STATE_ACTIVE);
pstn_call_state(pstn->call[PSTN_CALL_HOLD], CALL_STATE_HOLD);
/* send notify to active call */
notify_ind(pstn->call[PSTN_CALL_ACTIVE], OSMO_CC_NOTIFY_REMOTE_RETRIEVAL);
return;
}
/* if active call, put it on hold and setup new call, if not en-block dialing */
if (pstn->call[PSTN_CALL_ACTIVE]->cc_callref) {
PDEBUG(DTEL, DEBUG_INFO, "There is an active call only, so put it on hold and start a new one.\n");
/* swap ACTIVE call and call on HOLD */
swap_active_hold(pstn);
/* change state */
pstn_call_state(pstn->call[PSTN_CALL_HOLD], CALL_STATE_HOLD);
/* send notify to call on hold */
notify_ind(pstn->call[PSTN_CALL_HOLD], OSMO_CC_NOTIFY_REMOTE_HOLD);
/* start DTMF */
dtmf_on(pstn);
/* start pulse */
pulse_on(pstn);
if (!pstn->enblock) {
/* setup */
setup_ind(pstn, PSTN_CALL_ACTIVE, "", 0);
} else {
/* start dial timer */
timer_on(pstn, DIALTONE_TO, TIMER_IDENT_DIALING);
/* dial tone */
tone_on(pstn, TONE_DIALTONE, "dial");
/* change state */
pstn_call_state(pstn->call[PSTN_CALL_ACTIVE], CALL_STATE_ENBLOCK);
}
return;
}
}
static void v5_sig_ind(pstn_t *pstn, uint8_t *data, int len)
{
osmo_cc_msg_t *new_msg;
int pulses;
if (len < 3 && data[1] < 1) {
PDEBUG(DTEL, DEBUG_ERROR, "Received short V5 signal message, ignoring!\n");
@ -1277,10 +1333,10 @@ static void v5_sig_ind(pstn_t *pstn, uint8_t *data, int len)
case PSTN_V5_STEADY_SIGNAL_OFF_HOOK:
PDEBUG(DTEL, DEBUG_INFO, "Received steady off-kook signal.\n");
if (timer_running(&pstn->timer) && pstn->timer_ident == TIMER_IDENT_HOOKFLASH) {
PDEBUG(DTEL, DEBUG_INFO, "This was short, so this was a hookflash..\n");
PDEBUG(DTEL, DEBUG_INFO, "Performing hookflash, because on-hook was too short for hangup.\n");
/* stop timer */
timer_off(pstn);
goto hookflash;
hookflash(pstn);
}
/* clear dialing */
pstn->dialing[0] = '\0';
@ -1346,60 +1402,21 @@ static void v5_sig_ind(pstn_t *pstn, uint8_t *data, int len)
switch ((data[2] & 0x7f)) {
case PSTN_V5_PULSED_SIGNAL_ON_HOOK:
PDEBUG(DTEL, DEBUG_INFO, "Received pulsed on-kook signal.\n");
hookflash:
/* clear dialing */
pstn->dialing[0] = '\0';
/* if call on hold, swap calls */
if (pstn->call[PSTN_CALL_HOLD]->cc_callref) {
PDEBUG(DTEL, DEBUG_INFO, "There is a call on hold, so swap both calls.\n");
/* swap ACTIVE call and call on HOLD */
swap_active_hold(pstn);
/* send notify to call on hold */
notify_ind(pstn->call[PSTN_CALL_HOLD], OSMO_CC_NOTIFY_REMOTE_HOLD);
/* if waiting call, answer it */
if (pstn->call[PSTN_CALL_ACTIVE]->state != CALL_STATE_ACTIVE
&& pstn->call[PSTN_CALL_ACTIVE]->state != CALL_STATE_HOLD) {
/* setup confirm */
setup_cnf(pstn, PSTN_CALL_ACTIVE);
}
/* change state */
pstn_call_state(pstn->call[PSTN_CALL_ACTIVE], CALL_STATE_ACTIVE);
pstn_call_state(pstn->call[PSTN_CALL_HOLD], CALL_STATE_HOLD);
/* send notify to active call */
notify_ind(pstn->call[PSTN_CALL_ACTIVE], OSMO_CC_NOTIFY_REMOTE_RETRIEVAL);
break;
}
/* if active call, put it on hold and setup new call, if not en-block dialing */
if (pstn->call[PSTN_CALL_ACTIVE]->cc_callref) {
PDEBUG(DTEL, DEBUG_INFO, "There is a only an active call, so put it on hold and start a new one.\n");
/* swap ACTIVE call and call on HOLD */
swap_active_hold(pstn);
/* change state */
pstn_call_state(pstn->call[PSTN_CALL_HOLD], CALL_STATE_HOLD);
/* send notify to call on hold */
notify_ind(pstn->call[PSTN_CALL_HOLD], OSMO_CC_NOTIFY_REMOTE_HOLD);
/* start DTMF */
dtmf_on(pstn);
/* start pulse */
pulse_on(pstn);
if (!pstn->enblock) {
/* setup */
setup_ind(pstn, PSTN_CALL_ACTIVE, "", 0);
} else {
/* start dial timer */
timer_on(pstn, DIALTONE_TO, TIMER_IDENT_DIALING);
/* dial tone */
tone_on(pstn, TONE_DIALTONE, "dial");
/* change state */
pstn_call_state(pstn->call[PSTN_CALL_ACTIVE], CALL_STATE_ENBLOCK);
}
break;
if (pstn->recall && pstn->call[PSTN_CALL_ACTIVE]->state == CALL_STATE_ACTIVE) {
PDEBUG(DTEL, DEBUG_INFO, "Performing hookflash, on-hook pulse was received.\n");
hookflash(pstn);
}
break;
}
break;
case PSTN_V5_IE_DIGIT_SIGNAL:
PDEBUG(DTEL, DEBUG_INFO, "Received digit signal.\n");
pulses = data[2] & 0x0f;
PDEBUG(DTEL, DEBUG_INFO, "Received digit signal: %d pulses\n", pulses);
if (pulses == 1 && pstn->recall && pstn->call[PSTN_CALL_ACTIVE]->state == CALL_STATE_ACTIVE) {
PDEBUG(DTEL, DEBUG_INFO, "Performing hookflash, because digit '1' was dialled. (short hookflash)\n");
hookflash(pstn);
break;
}
if (!pstn->pulse_on)
break;
/* stop timer */
@ -1410,7 +1427,7 @@ hookflash:
tone_off(pstn);
/* convert pulses -> digit */
char called[2] = { '\0', '\0' };
switch (data[2] & 0x0f) {
switch (pulses) {
case 0:
PDEBUG(DTEL, DEBUG_ERROR, "Received 0 pulses, ignoring!\n");
break;