ソースを参照

modules/ims_charging: add support for final_unit_indication and redirect fn'ality in CCA

jaybeepee 9 年 前
コミット
46f188825d

+ 12 - 2
modules/ims_charging/Ro_data.c

@@ -296,10 +296,20 @@ void Ro_free_CCR(Ro_CCR_t *x) {
 }
 
 void Ro_free_CCA(Ro_CCA_t *x) {
-    if (!x) return;
+    str *p_str;
+	if (!x) return;
 
     if (x->mscc->final_unit_action) {
-        mem_free(x->mscc->final_unit_action, pkg);
+        if (x->mscc->final_unit_action->redirect_server) {
+			if (x->mscc->final_unit_action->redirect_server->server_address) {
+				p_str = x->mscc->final_unit_action->redirect_server->server_address;
+				if (p_str->len > 0 && p_str->s)
+					mem_free(p_str->s, pkg);
+				mem_free(p_str, pkg);
+			}
+		}
+		mem_free(x->mscc->final_unit_action, pkg);
+		
     }
     mem_free(x->mscc->granted_service_unit, pkg);
     mem_free(x->mscc, pkg);

+ 7 - 0
modules/ims_charging/Ro_data.h

@@ -362,14 +362,21 @@ typedef struct {
     uint32_t cc_output_octets;
 } granted_services_unit_t;
 
+typedef struct {
+    uint32_t address_type;
+    str* server_address;
+} redirect_server_t;
+
 typedef struct {
     uint32_t action;
+    redirect_server_t *redirect_server;
 } final_unit_indication_t;
 
 typedef struct {
     granted_services_unit_t *granted_service_unit;
     uint32_t validity_time;
     final_unit_indication_t *final_unit_action;
+    uint32_t resultcode;
 } multiple_services_credit_control_t;
 
 typedef struct {

+ 31 - 0
modules/ims_charging/ccr.c

@@ -277,6 +277,7 @@ Ro_CCA_t *Ro_parse_CCA_avps(AAAMessage *cca) {
     mscc->final_unit_action = fui;
 
     mscc->final_unit_action->action = -1;
+	mscc->final_unit_action->redirect_server = 0;
 
     AAA_AVP_LIST* avp_list = &cca->avpList;
     AAA_AVP_LIST mscc_avp_list;
@@ -321,6 +322,9 @@ Ro_CCA_t *Ro_parse_CCA_avps(AAAMessage *cca) {
                         case AVP_Validity_Time:
                             mscc->validity_time = get_4bytes(mscc_avp->data.s);
                             break;
+						case AVP_Result_Code:
+							mscc->resultcode = get_4bytes(mscc_avp->data.s);
+							break;
                         case AVP_Final_Unit_Indication:
                             y = cdp_avp->cdp->AAAUngroupAVPS(mscc_avp->data);
                             z = y.head;
@@ -329,6 +333,33 @@ Ro_CCA_t *Ro_parse_CCA_avps(AAAMessage *cca) {
                                     case AVP_Final_Unit_Action:
                                         mscc->final_unit_action->action = get_4bytes(z->data.s);
                                         break;
+									case AVP_Redirect_Server:
+										LM_DBG("Received redirect server\n");
+										redirect_server_t* redirect_server_info = 0;
+										mem_new(redirect_server_info, sizeof (redirect_server_t), pkg);
+										mscc->final_unit_action->redirect_server = redirect_server_info;
+										
+										AAA_AVP_LIST yy;
+										AAA_AVP *zz;
+										yy = cdp_avp->cdp->AAAUngroupAVPS(z->data);
+										zz = yy.head;
+										while (zz) {
+											switch (zz->code) {
+												case AVP_Redirect_Address_Type:
+													LM_DBG("Received redirect address type\n");
+													mscc->final_unit_action->redirect_server->address_type = get_4bytes(zz->data.s);
+													break;
+												case AVP_Redirect_Server_Address:
+													LM_DBG("Received redirect server address of [%.*s]\n", zz->data.len, zz->data.s);
+													str_dup_ptr(redirect_server_info->server_address, zz->data, pkg);
+													break;	
+												default:
+													LM_ERR("Unsupported Redirect Server AVP with code:[%d]\n", zz->code);
+											}
+											zz = zz->next;
+											cdp_avp->cdp->AAAFreeAVPList(&yy);
+										}
+										break;		
                                     default:
                                         LM_ERR("Unsupported Final Unit Indication AVP.\n");
                                 }

+ 70 - 1
modules/ims_charging/ims_ro.c

@@ -64,6 +64,7 @@ extern int video_rating_group;
 
 static int create_cca_return_code(int result);
 static int create_cca_result_code(int result);
+static int create_cca_fui_avps(int action, str* redirecturi);
 static void resume_on_initial_ccr(int is_timeout, void *param, AAAMessage *cca, long elapsed_msecs);
 static void resume_on_interim_ccr(int is_timeout, void *param, AAAMessage *cca, long elapsed_msecs);
 static void resume_on_termination_ccr(int is_timeout, void *param, AAAMessage *cca, long elapsed_msecs);
@@ -1246,6 +1247,8 @@ static void resume_on_initial_ccr(int is_timeout, void *param, AAAMessage *cca,
     struct cell *t = NULL;
     struct session_setup_data *ssd = (struct session_setup_data *) param;
     int error_code = RO_RETURN_ERROR;
+	str *redirecturi = 0;
+	int fui_action = 0;
 
     if (is_timeout) {
         counter_inc(ims_charging_cnts_h.ccr_timeouts);
@@ -1289,7 +1292,7 @@ static void resume_on_initial_ccr(int is_timeout, void *param, AAAMessage *cca,
     if (!ro_cca_data) {
         LM_ERR("Could not parse CCA message response.\n");
         error_code = RO_RETURN_ERROR;
-	create_cca_result_code(0);
+		create_cca_result_code(0);
         goto error0;
     }
     
@@ -1302,6 +1305,40 @@ static void resume_on_initial_ccr(int is_timeout, void *param, AAAMessage *cca,
         goto error1;
     }
 
+	if (ro_cca_data->mscc->final_unit_action) {
+		fui_action = ro_cca_data->mscc->final_unit_action->action;
+
+		if (fui_action == AVP_Final_Unit_Action_Redirect) {
+			if (ro_cca_data->mscc->final_unit_action->redirect_server) {
+				LM_DBG("FUI with action: [%d]", ro_cca_data->mscc->final_unit_action->action);
+
+				if (ro_cca_data->mscc->final_unit_action->action == AVP_Final_Unit_Action_Redirect) {
+					LM_DBG("Have REDIRECT action with address type of [%d]\n", ro_cca_data->mscc->final_unit_action->redirect_server->address_type);
+					if (ro_cca_data->mscc->final_unit_action->redirect_server->address_type == AVP_Redirect_Address_Type_SIP_URI) {
+						LM_DBG("SIP URI for redirect is [%.*s] with len of %d\n",
+							ro_cca_data->mscc->final_unit_action->redirect_server->server_address->len, ro_cca_data->mscc->final_unit_action->redirect_server->server_address->s,
+							ro_cca_data->mscc->final_unit_action->redirect_server->server_address->len);
+						redirecturi = ro_cca_data->mscc->final_unit_action->redirect_server->server_address;
+					} else {
+						LM_DBG("we don't cater for any redirect action which is not a SIP URI... ignoring [%d]\n", ro_cca_data->mscc->final_unit_action->redirect_server->address_type);
+					}
+				} else {
+					LM_DBG("ignoring final unit action which is not REDIRECT - [%d]\n", fui_action);
+				}
+			}
+		}
+	}
+	
+	/* create the AVPs cca_redirect_uri and cca_fui_action  for export to cfg file */
+	create_cca_fui_avps(fui_action, redirecturi);
+	
+	/* check result code at mscc level */
+	if (ro_cca_data->mscc->resultcode != 2001) {
+		LM_DBG("CCA failure at MSCC level with resultcode [%d]\n", ro_cca_data->mscc->resultcode);
+		error_code = RO_RETURN_FALSE;
+        goto error1;
+	}
+
     LM_DBG("Valid CCA response with time chunk of [%i] and validity [%i]\n",
             ro_cca_data->mscc->granted_service_unit->cc_time,
             ro_cca_data->mscc->validity_time);
@@ -1451,8 +1488,40 @@ static int create_cca_result_code(int result) {
     return 1;
 }
 
+static int create_cca_fui_avps(int action, str* redirecturi) {
+	int_str action_avp_val, action_avp_name, redirecturi_avp_val, redirecturi_avp_name;
+    action_avp_name.s.s = RO_AVP_CCA_FUI_ACTION;
+    action_avp_name.s.len = RO_AVP_CCA_FUI_ACTION_LENGTH;
+	redirecturi_avp_name.s.s = RO_AVP_CCA_FUI_REDIRECT_URI;
+    redirecturi_avp_name.s.len = RO_AVP_CCA_FUI_REDIRECT_URI_LENGTH;
+    char buf[10];
+	int rc;
+	
+    action_avp_val.n = action;
+    action_avp_val.s.len = snprintf(buf, 10, "%i", action);
+    action_avp_val.s.s = buf;
 
+    rc = add_avp(AVP_NAME_STR|AVP_VAL_STR, action_avp_name, action_avp_val);
 
+    if (rc < 0)
+        LM_ERR("Couldn't create ["RO_AVP_CCA_FUI_ACTION"] AVP\n");
+    else
+        LM_DBG("Created AVP ["RO_AVP_CCA_FUI_ACTION"] successfully: value=[%d]\n", action);
+	
+	if (redirecturi && redirecturi->len >0 && redirecturi->s) {
+		redirecturi_avp_val.s.len = redirecturi->len;
+		redirecturi_avp_val.s.s = redirecturi->s;
+
+		rc = add_avp(AVP_NAME_STR|AVP_VAL_STR, redirecturi_avp_name, redirecturi_avp_val);
+
+		if (rc < 0)
+			LM_ERR("Couldn't create ["RO_AVP_CCA_FUI_REDIRECT_URI"] AVP\n");
+		else
+			LM_DBG("Created AVP ["RO_AVP_CCA_FUI_REDIRECT_URI"] successfully: value=[%.*s]\n", redirecturi->len, redirecturi->s);
+	}
+	
+    return 1;
+}
 
 static int get_mac_avp_value(struct sip_msg *msg, str *value) {
     str mac_avp_name_str = str_init(RO_MAC_AVP_NAME);

+ 6 - 0
modules/ims_charging/mod.h

@@ -48,6 +48,12 @@
 #define RO_AVP_CCA_RESULT_CODE "cca_result_code"
 #define RO_AVP_CCA_RESULT_CODE_LENGTH 15
 
+#define RO_AVP_CCA_FUI_ACTION "cca_fui_action"
+#define RO_AVP_CCA_FUI_ACTION_LENGTH 14
+
+#define RO_AVP_CCA_FUI_REDIRECT_URI "cca_redirect_uri"
+#define RO_AVP_CCA_FUI_REDIRECT_URI_LENGTH 16
+
 #define RO_MAC_AVP_NAME	"$avp(ro_mac_value)"
 
 #define DB_DEFAULT_UPDATE_PERIOD	60