From f3b9db19fe94f6d9d2746e18b029eaea3f7a6adb Mon Sep 17 00:00:00 2001 From: Grzegorz Sluja <grzegorz.sluja@iopsys.eu> Date: Fri, 4 Apr 2025 11:09:44 +0200 Subject: [PATCH] Fix the issue of wrong handling the pcm_id, REF 16442 When the ACTION_RINGING_STOP is received for the call which is already in established state we should ignore it, otherwise in some cases the state of pcm is changed to invalid while the call is still active. Also add more debug covering each case of setting the pcm_callid. --- libvoice/common.c | 2 ++ line-dect.c | 46 +++++++++++++++++++++++------------- line.c | 60 +++++++++++++++++++++++++++++++++++++---------- line.h | 1 + 4 files changed, 81 insertions(+), 28 deletions(-) diff --git a/libvoice/common.c b/libvoice/common.c index f75cdd4..53b4680 100644 --- a/libvoice/common.c +++ b/libvoice/common.c @@ -124,7 +124,9 @@ int voice_line_preinit(void) { lines[i].type = terminal_info.voice_ports[i]; ENDPT_DBG("lines[%d].type=%d\n", i, lines[i].type); lines[i].pcm_callid[PCM_0] = CALLID_INVALID; + ENDPT_DBG("line: %d set pcm_callid[%d] to %d\n", i, PCM_0, lines[i].pcm_callid[PCM_0]); lines[i].pcm_callid[PCM_1] = CALLID_INVALID; + ENDPT_DBG("line: %d set pcm_callid[%d] to %d\n", i, PCM_1, lines[i].pcm_callid[PCM_1]); } return 0; diff --git a/line-dect.c b/line-dect.c index 74b3048..9064d44 100644 --- a/line-dect.c +++ b/line-dect.c @@ -216,6 +216,8 @@ int ubus_cb_dectmngr_replied(struct line_req_t *req, enum ubus_msg_status reply_ if(!req) return -1; + struct line_t *line = &lines[req->line]; + ENDPT_DBG("got answer req %p from dectmngr, action: %d, line: %d, pcmId: %d, conId: %d\n", req, req->action, req->line, req->pcm_id, req->connection_id); pcm_states_dump(__func__, req->line); @@ -226,28 +228,40 @@ int ubus_cb_dectmngr_replied(struct line_req_t *req, enum ubus_msg_status reply_ reply_status = UBUS_STATUS_UNKNOWN_ERROR; } break; - case ACTION_CONN_CLOSE: case ACTION_RINGING_STOP: - if (req->pcm_id == PCM_0 || req->pcm_id == PCM_1) { - lines[req->line].pcm_callid[req->pcm_id] = CALLID_INVALID; + if (get_callid_state(line->pcm_callid[req->pcm_id]) == CALLID_ESTABLISHED) + break; // Don't clear if call is already established + // intentional fallthrough + case ACTION_CONN_CLOSE: + if (is_valid_pcm_id(req->pcm_id)) { + line->pcm_callid[req->pcm_id] = CALLID_INVALID; + ENDPT_DBG("line: %d set pcm_callid[%d] to %d\n", req->line, req->pcm_id, line->pcm_callid[req->pcm_id]); } else if (req->pcm_id == -1) { - // Close all calls - lines[req->line].pcm_callid[PCM_0] = CALLID_INVALID; - lines[req->line].pcm_callid[PCM_1] = CALLID_INVALID; + // Clear both PCM slots + for (int i = 0; i <= PCM_1; ++i) { + line->pcm_callid[i] = CALLID_INVALID; + ENDPT_DBG("line: %d set pcm_callid[%d] to %d\n", req->line, i, CALLID_INVALID); + } + } + // If no established calls left, close connection + if (get_callid_state(line->pcm_callid[PCM_0]) != CALLID_ESTABLISHED && + get_callid_state(line->pcm_callid[PCM_1]) != CALLID_ESTABLISHED) { + reply_status = voice_connection_close(req->line, req->line) + ? UBUS_STATUS_UNKNOWN_ERROR + : UBUS_STATUS_OK; } - if (get_callid_state(lines[req->line].pcm_callid[PCM_0]) == CALLID_ESTABLISHED || - get_callid_state(lines[req->line].pcm_callid[PCM_1]) == CALLID_ESTABLISHED) - break; - reply_status = voice_connection_close(req->line, req->line) ? // Close regardless of any dectmngr error. - UBUS_STATUS_UNKNOWN_ERROR : UBUS_STATUS_OK; break; case ACTION_SIG_RING: - if ((req->pcm_id == PCM_0 && get_callid_state(lines[req->line].pcm_callid[PCM_1]) == CALLID_OBTAINING) || - (req->pcm_id == PCM_1 && get_callid_state(lines[req->line].pcm_callid[PCM_0]) == CALLID_OBTAINING)) - break; - if (req->pcm_id == PCM_0 || req->pcm_id == PCM_1) - lines[req->line].pcm_callid[req->pcm_id] = CALLID_OBTAINING; + { + int other_pcm = (req->pcm_id == PCM_0) ? PCM_1 : PCM_0; + if (is_valid_pcm_id(req->pcm_id)) { + if (get_callid_state(line->pcm_callid[other_pcm]) != CALLID_OBTAINING) { + line->pcm_callid[req->pcm_id] = CALLID_OBTAINING; + ENDPT_DBG("line: %d set pcm_callid[%d] to %d\n", req->line, req->pcm_id, CALLID_OBTAINING); + } + } break; + } default: break; } diff --git a/line.c b/line.c index 5f29336..762568b 100644 --- a/line.c +++ b/line.c @@ -44,6 +44,11 @@ callid_state get_callid_state(int call_id) { return CALLID_ESTABLISHED; } +bool is_valid_pcm_id(int id) +{ + return id == PCM_0 || id == PCM_1; +} + static int send_dect_event_to_asterisk(int line, struct dect_event_t dectEvnt) { struct line_event_t *msg; @@ -309,6 +314,7 @@ int line_signal(int line, const char *signame, const char *data, struct voice_ub { const struct voice_signal_t *sig; int res = 0; + int pcm = PCM_0; ENDPT_DBG("line=%d(type:%d), signame=%s, data=%s\n", line, lines[line].type, signame, data); @@ -328,8 +334,13 @@ int line_signal(int line, const char *signame, const char *data, struct voice_ub case VOICE_SIG_CALLID: case VOICE_SIG_RINGING: if(atoi(data) == 0) { - res = line_signal_ring(line, get_callid_state(lines[line].pcm_callid[PCM_0]) == CALLID_OBTAINING ? - PCM_0 : PCM_1, sig->signal, data, ubus_req); + if ( get_callid_state(lines[line].pcm_callid[PCM_0]) == CALLID_OBTAINING || + get_callid_state(lines[line].pcm_callid[PCM_0]) == CALLID_INVALID ) + pcm = PCM_0; + else + pcm = PCM_1; + + res = line_signal_ring(line, pcm, sig->signal, data, ubus_req); lines[line].signaled_call_waiting = 0; } else { res = line_signal_ring(line, get_callid_state(lines[line].pcm_callid[PCM_0]) == CALLID_INVALID ? @@ -430,10 +441,14 @@ int line_new_connection_by_asterisk(int line, int connection, struct voice_ubus_ ENDPT_DBG("%s line: %d, connection: %d\n", __func__, line, connection); pcm_states_dump(__func__, line); - if (get_callid_state(lines[line].pcm_callid[PCM_0]) == CALLID_OBTAINING) + if (get_callid_state(lines[line].pcm_callid[PCM_0]) == CALLID_OBTAINING) { lines[line].pcm_callid[PCM_0] = connection; - else if (get_callid_state(lines[line].pcm_callid[PCM_1]) == CALLID_OBTAINING) + ENDPT_DBG("line: %d set pcm_callid[%d] to %d\n", line, PCM_0, lines[line].pcm_callid[PCM_0]); + } + else if (get_callid_state(lines[line].pcm_callid[PCM_1]) == CALLID_OBTAINING) { lines[line].pcm_callid[PCM_1] = connection; + ENDPT_DBG("line: %d set pcm_callid[%d] to %d\n", line, PCM_1, lines[line].pcm_callid[PCM_1]); + } if (lines[line].type == VOICE_LINE_DECT) { if (voice_line_is_offhook(line) || voice_line_get_connection_count(line) > 0) { @@ -509,10 +524,12 @@ int line_close_connection_by_asterisk(int line, int connection, struct voice_ubu get_callid_state(lines[line].pcm_callid[PCM_1]) == CALLID_INVALID) { line_req->pcm_id = PCM_0; lines[line].pcm_callid[PCM_0] = CALLID_INVALID; + ENDPT_DBG("line: %d set pcm_callid[%d] to %d\n", line, PCM_0, lines[line].pcm_callid[PCM_0]); } else if (get_callid_state(lines[line].pcm_callid[PCM_1]) == CALLID_ESTABLISHED && get_callid_state(lines[line].pcm_callid[PCM_0]) == CALLID_INVALID) { line_req->pcm_id = PCM_1; lines[line].pcm_callid[PCM_1] = CALLID_INVALID; + ENDPT_DBG("line: %d set pcm_callid[%d] to %d\n", line, PCM_1, lines[line].pcm_callid[PCM_1]); } line_req->action = ACTION_CONN_CLOSE; if (connection == -1) { @@ -527,10 +544,14 @@ int line_close_connection_by_asterisk(int line, int connection, struct voice_ubu break; default: - if (get_callid_state(lines[line].pcm_callid[PCM_0]) == CALLID_ESTABLISHED) + if (get_callid_state(lines[line].pcm_callid[PCM_0]) == CALLID_ESTABLISHED) { lines[line].pcm_callid[PCM_0] = CALLID_INVALID; - else if (get_callid_state(lines[line].pcm_callid[PCM_1]) == CALLID_ESTABLISHED) + ENDPT_DBG("line: %d set pcm_callid[%d] to %d\n", line, PCM_0, lines[line].pcm_callid[PCM_0]); + } + else if (get_callid_state(lines[line].pcm_callid[PCM_1]) == CALLID_ESTABLISHED) { lines[line].pcm_callid[PCM_1] = CALLID_INVALID; + ENDPT_DBG("line: %d set pcm_callid[%d] to %d\n", line, PCM_1, lines[line].pcm_callid[PCM_1]); + } return voice_connection_close(line, line); } @@ -575,9 +596,11 @@ int line_release_connection_by_asterisk(int line, int connection, struct voice_u if (lines[line].pcm_callid[PCM_0] == connection) { line_req->pcm_id = PCM_0; lines[line].pcm_callid[PCM_0] = CALLID_INVALID; + ENDPT_DBG("line: %d set pcm_callid[%d] to %d\n", line, PCM_0, lines[line].pcm_callid[PCM_0]); } else if (lines[line].pcm_callid[PCM_1] == connection) { line_req->pcm_id = PCM_1; lines[line].pcm_callid[PCM_1] = CALLID_INVALID; + ENDPT_DBG("line: %d set pcm_callid[%d] to %d\n", line, PCM_1, lines[line].pcm_callid[PCM_1]); } line_req->action = ACTION_CONN_CLOSE; memcpy(&line_req->ubus, ubus_req, sizeof(struct voice_ubus_req_t)); @@ -588,10 +611,14 @@ int line_release_connection_by_asterisk(int line, int connection, struct voice_u break; default: - if (lines[line].pcm_callid[PCM_0] == connection) + if (lines[line].pcm_callid[PCM_0] == connection) { lines[line].pcm_callid[PCM_0] = CALLID_INVALID; - else if (lines[line].pcm_callid[PCM_1] == connection) + ENDPT_DBG("line: %d set pcm_callid[%d] to %d\n", line, PCM_0, lines[line].pcm_callid[PCM_0]); + } + else if (lines[line].pcm_callid[PCM_1] == connection) { lines[line].pcm_callid[PCM_1] = CALLID_INVALID; + ENDPT_DBG("line: %d set pcm_callid[%d] to %d\n", line, PCM_1, lines[line].pcm_callid[PCM_1]); + } return voice_connection_close(line, line); } @@ -610,10 +637,14 @@ int line_update_connection_by_pbx(int line, int pcm_callid) if(lines[line].type != VOICE_LINE_DECT) return 0; - if (get_callid_state(lines[line].pcm_callid[PCM_0]) == CALLID_OBTAINING) + if (get_callid_state(lines[line].pcm_callid[PCM_0]) == CALLID_OBTAINING) { lines[line].pcm_callid[PCM_0] = pcm_callid; - else if (get_callid_state(lines[line].pcm_callid[PCM_1]) == CALLID_OBTAINING) + ENDPT_DBG("line: %d set pcm_callid[%d] to %d\n", line, PCM_0, lines[line].pcm_callid[PCM_0]); + } + else if (get_callid_state(lines[line].pcm_callid[PCM_1]) == CALLID_OBTAINING) { lines[line].pcm_callid[PCM_1] = pcm_callid; + ENDPT_DBG("line: %d set pcm_callid[%d] to %d\n", line, PCM_1, lines[line].pcm_callid[PCM_1]); + } return 0; } @@ -632,8 +663,9 @@ int line_new_connection_by_dect(int line, const char *cid, int pcm, struct voice ENDPT_DBG("line=%d, pcm=%d, cid=%s\n", line, pcm, cid); pcm_states_dump(__func__, line); - if (pcm == PCM_0 || pcm == PCM_1) { + if (is_valid_pcm_id(pcm)) { lines[line].pcm_callid[pcm] = CALLID_OBTAINING; + ENDPT_DBG("line: %d set pcm_callid[%d] to %d\n", line, pcm, lines[line].pcm_callid[pcm]); lines[line].signaled_call_waiting = 0; } @@ -739,8 +771,10 @@ int line_close_connection_by_dect(int line, int pcm, struct voice_ubus_req_t *ub get_callid_state(lines[line].pcm_callid[PCM_1]) <= CALLID_OBTAINING) { if(pcm == CALL_DEFAULT0 || pcm == CALL_DEFAULT1) { lines[line].pcm_callid[pcm] = CALLID_INVALID; + ENDPT_DBG("line: %d set pcm_callid[%d] to %d\n", line, pcm, lines[line].pcm_callid[pcm]); if (get_callid_state(lines[line].pcm_callid[1-pcm]) == CALLID_OBTAINING) { lines[line].pcm_callid[1-pcm] = CALLID_INVALID; + ENDPT_DBG("line: %d set pcm_callid[%d] to %d\n", line, 1-pcm, lines[line].pcm_callid[1-pcm]); } } voice_line_simulate_hook(line, VOICE_EVT_ONHOOK); @@ -748,8 +782,10 @@ int line_close_connection_by_dect(int line, int pcm, struct voice_ubus_req_t *ub pcm, UBUS_STATUS_OK); } - if(pcm == CALL_DEFAULT0 || pcm == CALL_DEFAULT1) + if(pcm == CALL_DEFAULT0 || pcm == CALL_DEFAULT1) { lines[line].pcm_callid[pcm] = CALLID_INVALID; + ENDPT_DBG("line: %d set pcm_callid[%d] to %d\n", line, pcm, lines[line].pcm_callid[pcm]); + } if(send_dect_event_to_asterisk(line, dect_event_map[DECT_EVT_RELEASE])) return -1; diff --git a/line.h b/line.h index a289c46..7100a67 100644 --- a/line.h +++ b/line.h @@ -67,5 +67,6 @@ int line_close_connection_by_dect(int line, int pcm, struct voice_ubus_req_t *ub int line_signal(int line, const char *signame, const char *data, struct voice_ubus_req_t *ubus_req); void pcm_states_dump(const char* func, int line); callid_state get_callid_state(int call_id); +bool is_valid_pcm_id(int id); #endif -- GitLab