Module: kamailio Branch: master Commit: 956be0edcd816134650c5efccb7965fccb4d5916 URL: https://github.com/kamailio/kamailio/commit/956be0edcd816134650c5efccb7965fc...
Author: jaybeepee jason.penton@gmail.com Committer: jaybeepee jason.penton@gmail.com Date: 2015-09-11T11:44:31+02:00
modules/cdp: fixed race condition between CCR update and CCR terminate - lean priority towards T
---
Modified: modules/cdp/acctstatemachine.c
---
Diff: https://github.com/kamailio/kamailio/commit/956be0edcd816134650c5efccb7965fc... Patch: https://github.com/kamailio/kamailio/commit/956be0edcd816134650c5efccb7965fc...
---
diff --git a/modules/cdp/acctstatemachine.c b/modules/cdp/acctstatemachine.c index d4e524d..31304d2 100644 --- a/modules/cdp/acctstatemachine.c +++ b/modules/cdp/acctstatemachine.c @@ -210,29 +210,41 @@ inline int cc_acc_client_stateful_sm_process(cdp_session_t* s, int event, AAAMes } break; case ACC_CC_ST_PENDING_U: - if (event == ACC_CC_EV_RECV_ANS && msg && !is_req(msg)) { - rc = get_result_code(msg); - if (rc >= 2000 && rc < 3000) { - event = ACC_CC_EV_RECV_ANS_SUCCESS; - } else { - event = ACC_CC_EV_RECV_ANS_UNSUCCESS; - } - } - switch (event) { - case ACC_CC_EV_RECV_ANS_SUCCESS: - x->state = ACC_CC_ST_OPEN; - LM_DBG("success CCA for UPDATE\n"); - update_gsu_response_timers(x, msg); - break; - case ACC_CC_EV_RECV_ANS_UNSUCCESS: - //TODO: check whether we grant or terminate service to callback clients - x->state = ACC_CC_ST_DISCON; - LM_ERR("update failed... going back to IDLE/DISCON\n"); - break; - default: - LM_ERR("Received unknown event [%d] in state [%d]\n", event, x->state); - break; - } + + /**Richard added Aug 5 - there is a potential race condition where you may send a CCR-U immediately followed by CCR-T + * and then receive a CCA-T while in state ACC_CC_ST_PENDING_U (e.g. if update timer and dialog termination at same time) + * In this event you would incorrectly ignore the CCR-T + * Solution is to change state to change state to ACC_CC_ST_PENDING_T if CCR-T is sent while in this state */ + if (event == ACC_CC_EV_SEND_REQ && msg && get_accounting_record_type(msg) == 4 /*TERMINATE RECORD*/) { + LM_ERR("Received CCR-T while in state ACC_CC_ST_PENDING_U, just going to change to ACC_CC_ST_PENDING_T\n"); + s->u.cc_acc.state = ACC_CC_ST_PENDING_T; + //update our reservation and its timers... + update_gsu_request_timers(x, msg); + } else { + if (event == ACC_CC_EV_RECV_ANS && msg && !is_req(msg)) { + rc = get_result_code(msg); + if (rc >= 2000 && rc < 3000) { + event = ACC_CC_EV_RECV_ANS_SUCCESS; + } else { + event = ACC_CC_EV_RECV_ANS_UNSUCCESS; + } + } + switch (event) { + case ACC_CC_EV_RECV_ANS_SUCCESS: + x->state = ACC_CC_ST_OPEN; + LM_DBG("success CCA for UPDATE\n"); + update_gsu_response_timers(x, msg); + break; + case ACC_CC_EV_RECV_ANS_UNSUCCESS: + //TODO: check whether we grant or terminate service to callback clients + x->state = ACC_CC_ST_DISCON; + LM_ERR("update failed... going back to IDLE/DISCON\n"); + break; + default: + LM_ERR("Received unknown event [%d] in state [%d]\n", event, x->state); + break; + } + } break; case ACC_CC_ST_DISCON: switch (event) {