[sr-dev] git:master:956be0ed: modules/cdp: fixed race condition between CCR update and CCR terminate - lean priority towards T

jaybeepee jason.penton at gmail.com
Fri Sep 11 11:45:53 CEST 2015


Module: kamailio
Branch: master
Commit: 956be0edcd816134650c5efccb7965fccb4d5916
URL: https://github.com/kamailio/kamailio/commit/956be0edcd816134650c5efccb7965fccb4d5916

Author: jaybeepee <jason.penton at gmail.com>
Committer: jaybeepee <jason.penton at 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/956be0edcd816134650c5efccb7965fccb4d5916.diff
Patch: https://github.com/kamailio/kamailio/commit/956be0edcd816134650c5efccb7965fccb4d5916.patch

---

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) {




More information about the sr-dev mailing list