/****************
 Contributed by: Krishnan Srinivasan <hsirk_6@yahoo.com>
 License: to be specified.
 TODO:
 
 ****************/

#include "extension.h"
#include <signal.h>
#include <time.h>
#include <math.h>
#include "sh_app.h"
#include "sh_conf.h"
#include "../../include/gy_message.h"

#define	_TEST_CCA	0
#define   PS_ENABLED	0
#define   FD_DEBUG_PROCESS 1

#define AUTH_APP_ID			16777238
#define VENDOR_ID_3GPP		10415
/* The content of this file follows the same structure as dict_base_proto.c */

void dump_sess_eyec(struct session *sess, const char *);

static long ts_sec, ts_msec;
static long gx_start_ts = 0;

static int gx_rec_ccr( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
static void gx_rec_cca(void *para, struct msg **msg);
_gy_port *gy_get_port_by_cxt_id(char *cxt_id);

static struct disp_hdl * ccr_cb_hdl = NULL; /* handler for ccr req cb */
//static struct disp_hdl * cca_cb_hdl = NULL; /* handler for cca req cb */
// static struct disp_hdl * reauth_cb_hdl = NULL; /* handler for cca req cb */

struct dict_object *ccr_cmd = NULL;
struct dict_object *cca_cmd = NULL;
struct dict_object *dataobj_re_auth_request_type = NULL;
struct dict_object *session_id = NULL;
struct dict_object *origin_host = NULL;
struct dict_object *origin_realm = NULL;
struct dict_object *dest_host = NULL;
struct dict_object *dest_realm = NULL;
struct dict_object *reauth_cmd = NULL;
struct dict_object *auth_app_id    = NULL; 
struct dict_object *service_cxt_id = NULL ; 
struct dict_object *cc_req_type    = NULL; 
struct dict_object *cc_req_num	= NULL;
struct dict_object *result_code	= NULL;

struct dict_object *requested_action = NULL;
struct dict_object *check_balance_result = NULL;

/* fj added 20160802 */
struct dict_object *event_timestamp = NULL;
struct dict_object *subscription_id = NULL, *subscription_id_type = NULL, *subscription_id_data = NULL;
struct dict_object *service_information = NULL;
struct dict_object *ims_information = NULL;
struct dict_object *sms_information = NULL;
struct dict_object *time_stamps = NULL;

struct dict_object *service_identifier = NULL;
struct dict_object *rating_group = NULL;
struct dict_object *multiple_services_indicator = NULL;
struct dict_object *multiple_services_credit_control = NULL;
struct dict_object *requested_service_unit = NULL;
struct dict_object *cc_time = NULL;
struct dict_object *cc_total_octects = NULL;
struct dict_object *reporting_reason = NULL;
struct dict_object *final_unit_action = NULL;

struct dict_object *ps_information = NULL;

extern struct dict_object *g_dict_dcca;
struct dict_object *term_cause = NULL;

struct session *g_sess = NULL;
struct session_handler *g_hdlr = NULL;

//static struct dict_avp_request __avp;

enum gx_state
{
	STATE_INIT = 0,
	STATE_INTERMEDIATE ,
	STATE_FINAL
};
struct gx_sm_t
{
	enum gx_state state;
	pthread_t tid;
	struct fifo *events;
	pthread_mutex_t p_sm_mtx;
	int req_num;
	struct session *sess;  
} g_gx_sm;


/*---------------------------------*/
static pthread_mutex_t gy_port_lock = PTHREAD_MUTEX_INITIALIZER;
//static pthread_mutex_t gy_cca_lock = PTHREAD_MUTEX_INITIALIZER;

struct session *gy_sess[MAX_GY_PORT];

static _gy_space gy_space;
static _gy_stat    gy_stat;
extern GHashTable *g_sess_hash;
//static pthread_mutex_t gy_msg_mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t sess_hash_mutx = PTHREAD_MUTEX_INITIALIZER;

/* -------------------------------------------*/
int	pps_recv_gy_process(_gy_msg  *gy_ptr);
//static int gx_add_msg_to_list(_gy_msg *pInMsg);
int pps_debug_info(char *app_name, char *str_to_show);
int pps_debug_flag_for_fd();
unsigned int GetLocalIP( );
extern int pps_ro_gy_cb(_gy_msg  *gy_ptr);
int fdAsciiToBcdR(char *bcd_buf, int *bcd_buf_len, const char *ascii_buf, int len)
{
	int  i;
	char ch;

	*bcd_buf_len = len%2 + len/2;
	
	for(i = 0; i < len; i++)
	{
		ch = ascii_buf[i];
		if(ch >='a' )       ch -= 'a' -10;
		else if(ch  >='A')  ch -= 'A'-10;
		else              ch -= '0';
		if(i & 1) *(bcd_buf++) |= ch<<4;
		else     *(bcd_buf) = ch & 0x0f;
	}

	if(len%2)
	{
		*(bcd_buf++) |= 0xf0;
	}

	return 0;
}

int fdAsciiToBcd(unsigned char *bcd_buf, int *bcd_buf_len, const char *ascii_buf, int len)
{
   int  i;
   char ch;

  *bcd_buf_len = len%2 + len/2;

   
   for(i=0;i<len;i++)
   {
      ch =ascii_buf[i];
	  if(ch>='a')       ch -='a' -10;
	  else if(ch>='A')  ch -='A'-10;
	  else              ch -='0';
	  if(i &1) *(bcd_buf++) |=ch & 0x0f;
	  else     *(bcd_buf) =ch<<4;
    }
	if(len%2)
	{
		*(bcd_buf++) |= 0x0f;
	}
    
    return 0;
}


/* -------------------------------------------*/
static void gy_port_init(_gy_port *gy_port_ptr, int index)
{
	if (gy_port_ptr == NULL)
	{
		return;
	}

	gy_port_ptr->used_flag = 0;
	gy_port_ptr->index = index;
	gy_port_ptr->updated_ts = ts_sec;
	gy_port_ptr->app_port = INVALID_GY_PORT;
	gy_port_ptr->context_id[0] = '\0';
	gy_port_ptr->service_type = 0;
	gy_port_ptr->request_number = 0;
	gy_port_ptr->as_client = 0;

	return ;
}

// start==================================
static int print_duplicated_sess_id(const char *cxt_id)
{
	int loop=0;
	FILE *fpSess=NULL;

	fpSess = fopen("../log/dul_sess_id.txt","a");
	if(fpSess == NULL)
		return 0;

	fprintf(fpSess,"now ts=%ld, sess: %s\r\n", ts_sec, cxt_id);

	fclose(fpSess);
	
	return 1;
}

int gy_assign_port(char *cxt_id)
{
	int i, index, retval = INVALID_GY_PORT;
	_gy_port *gy_port_ptr = NULL;

// check if session id already in use========start
	gy_port_ptr = gy_get_port_by_cxt_id(cxt_id);
	if (gy_port_ptr != NULL)
	{
		print_duplicated_sess_id(cxt_id);
		return retval;
	}
	
	CHECK_POSIX_DO( pthread_mutex_lock(&gy_port_lock), { ASSERT(0); } );

	for(i=0; i<MAX_GY_PORT; i++)
	{
		index = gy_space.cur_index++;
		gy_space.cur_index %= MAX_GY_PORT;
		if(gy_space.gy_port[index].used_flag == 0)
		{
			gy_port_ptr = &gy_space.gy_port[index];
			gy_port_init(gy_port_ptr, index);
			
			gy_port_ptr->used_flag = 1;
			strcpy(gy_port_ptr->context_id, cxt_id);
			
			gy_space.used_ports ++;
			retval = index;

			if(pps_debug_flag_for_fd())
			{
				char tmp_info[1024];
				
				sprintf(tmp_info, " [fd=%04d][app=0000], ts=%ld.%03ld, used_pots=%d, %s\r\n",
					index, ts_sec, ts_msec, gy_space.used_ports, __FUNCTION__);
				pps_debug_info("diameter", tmp_info);				
			}
			
			break;
		}
	}

	CHECK_POSIX_DO( pthread_mutex_unlock(&gy_port_lock), { ASSERT(0); } );	

	if (gy_port_ptr != NULL)
	{
		pthread_mutex_lock(&sess_hash_mutx);
		//g_hash_table_insert(g_sess_hash, strdup(context_id), (gpointer)gy_cxt_tb.gy_cxt_port[index].index);
		g_hash_table_insert(g_sess_hash, gy_port_ptr->context_id, (gpointer)gy_port_ptr);
		pthread_mutex_unlock(&sess_hash_mutx);
	}
	
	return retval;
}

int gy_release_port(unsigned short index)
{
	if(index<MAX_GY_PORT)
	{
		_gy_port *gy_port_ptr = NULL;
		gy_port_ptr = &gy_space.gy_port[index];

		if(gy_port_ptr->used_flag)
		{
			pthread_mutex_lock(&sess_hash_mutx);
			if(g_sess_hash != NULL)
			g_hash_table_remove(g_sess_hash, gy_port_ptr->context_id);// delete hash index
			pthread_mutex_unlock(&sess_hash_mutx);

			CHECK_POSIX_DO( pthread_mutex_lock(&gy_port_lock), { ASSERT(0); } );
			gy_port_init(gy_port_ptr, index);
			gy_space.used_ports --;
			CHECK_POSIX_DO( pthread_mutex_unlock(&gy_port_lock), { ASSERT(0); } );	
		}

		if(0)
		{
			char tmp_info[1024];
			
			sprintf(tmp_info, " [fd=%04d][app=%04d], ts=%ld.%03ld, %s, used_ports=%d\r\n",
				index, gy_space.gy_port[index].app_port,ts_sec, ts_msec, 
				 __FUNCTION__, 
				gy_space.used_ports);
			pps_debug_info("diameter", tmp_info);				
			
		}
		
	}

	return 1;
}

_gy_port *gy_get_port_space(unsigned short index)
{
	if(index<MAX_GY_PORT)
	{
		if(gy_space.gy_port[index].used_flag)
		{
			return &gy_space.gy_port[index];
		}
	}

	return NULL;
}

_gy_port *gy_get_port_by_cxt_id(char *cxt_id)
{
	_gy_port *gy_port_ptr = NULL;
	
	pthread_mutex_lock(&sess_hash_mutx);
	gy_port_ptr = g_hash_table_lookup(g_sess_hash, cxt_id);
	pthread_mutex_unlock(&sess_hash_mutx);

	return gy_port_ptr;
}


/*---------------------------------*/

int gx_send_ccr(struct gx_sm_t **gx_sm  , struct dict_object *cmd_r ) ;

void gx_sig_hdlr(void);
int gx_send_ccr_real(struct gx_sm_t **sm , struct dict_object *cmd_r, _gy_msg *msg_ptr) ;
int	gx_stat_increase_recv_cca(int type);
int	gx_stat_increase_send_cca(int type);
int	gx_stat_increase_recv_ccr(int type);
int	gx_stat_increase_send_ccr(int type);
int time_t_to_diameter_timestamp(char *strTime);
void *gx_sm_th(void *sm);

int app_gx_entry(char * conffile)
{  
	{
		CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Credit-Control-Request", &ccr_cmd, ENOENT));
		CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Credit-Control-Answer", &cca_cmd, ENOENT));
	}
	
	// Do registeration and init stuff
	{
		LOG_D("Initializing dispatch callbacks for Gx interface");

		if(ta_conf->mode & MODE_SERV )
		{
			struct disp_when data;
			memset(&data, 0, sizeof(data));
			data.app = g_dict_dcca;
			data.command = ccr_cmd;
			/* Now specific handler for CCR-CMD */
			CHECK_FCT( fd_disp_register( gx_rec_ccr, DISP_HOW_CC, &data, NULL, &ccr_cb_hdl ) );

			LOG_D("fj app_gx_entry register gx_rec_ccr");
		}

#ifdef REAUTH
		CHECK_FCT(fd_dict_search(fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Re-Auth-Request", &reauth_cmd, ENOENT));
		memset(&data, 0, sizeof(data));
		data.app = g_dict_dcca;
		data.command = reauth_cmd;
		printf("register REAUTH\n");
		CHECK_FCT( fd_disp_register( reauth_cb, DISP_HOW_CC, &data, NULL, &reauth_cb_hdl ) );
#endif
	}

	SEARCH_AVP_("Session-Id", 0, &session_id);
	SEARCH_AVP_("Origin-Host", 0, &origin_host);
	SEARCH_AVP_("Origin-Realm", 0, &origin_realm);
	SEARCH_AVP_("Destination-Host", 0, &dest_host);
	SEARCH_AVP_("Destination-Realm", 0, &dest_realm);
	SEARCH_AVP_("Auth-Application-Id", 0, &auth_app_id);
	SEARCH_AVP_("Service-Context-Id", 0, &service_cxt_id);
	SEARCH_AVP_("CC-Request-Type", 0, &cc_req_type);
	SEARCH_AVP_("Termination-Cause", 0, &term_cause);
	SEARCH_AVP_("CC-Request-Number", 0, &cc_req_num);
	SEARCH_AVP_("Requested-Action", 0, &requested_action);
	SEARCH_AVP_("Result-Code", 0, &result_code);
	SEARCH_AVP_("Check-Balance-Result", 0, &check_balance_result);

	/* fj added 20160802 */
	SEARCH_AVP_("Event-Timestamp", 0, &event_timestamp);
	SEARCH_AVP_("Subscription-Id", 0, &subscription_id);
	SEARCH_AVP_("Service-Information", 10415, &service_information);
	SEARCH_AVP_("IMS-Information", 10415, &ims_information);
	SEARCH_AVP_("SMS-Information", 10415, &sms_information);
	SEARCH_AVP_("Time-Stamps", 10415, &time_stamps);

	SEARCH_AVP_("PS-Information", 10415, &ps_information);
	
	SEARCH_AVP_("Service-Identifier", 0, &service_identifier);
	SEARCH_AVP_("Rating-Group", 0, &rating_group);
	SEARCH_AVP_("Multiple-Services-Indicator", 0, &multiple_services_indicator);
	SEARCH_AVP_("Multiple-Services-Credit-Control", 0, &multiple_services_credit_control);
	SEARCH_AVP_("Requested-Service-Unit", 0, &requested_service_unit);
	
    CHECK_FCT(fd_sess_handler_create( &g_hdlr, (void *)free, NULL, NULL));
    CHECK_FCT( fd_fifo_new(&g_gx_sm.events, 0));  
    CHECK_FCT( fd_disp_app_support( g_dict_dcca, NULL, 1 , 0));
    CHECK_FCT( fd_event_trig_regcb(SIGUSR1, "app_gx", gx_sig_hdlr ) );

out:
	LOG_D("Extension 'Gx' initialized");
	return 0;
}

void * gx_sm_th(void *sm)
{
	struct gx_sm_t *gx_sm = (struct gx_sm_t *) sm;
	struct timespec tout;
	int evt_code;

	CHECK_SYS_DO( clock_gettime( CLOCK_REALTIME, &tout), goto out);
	tout.tv_sec =+ 60 ;
	
    while(1)
	{
		fd_event_timedget(gx_sm->events, &tout , ETIMEDOUT, &evt_code, NULL, NULL );
		CHECK_SYS_DO( clock_gettime( CLOCK_REALTIME, &tout), goto out);
		printf("in tout sec %d\n", (int)tout.tv_sec); 
		if(evt_code == ETIMEDOUT)
		{
			gx_send_ccr(&gx_sm, ccr_cmd);
			gx_sm->req_num++ ;
			gx_sm->state = STATE_INTERMEDIATE;
			CHECK_SYS_DO( clock_gettime( CLOCK_REALTIME, &tout), goto out);
			tout.tv_sec += 30 ;
		}
		// printf("press enter\n");
		// getchar();
    }
	
out:
	
	return NULL;
}
//TBD
int init_gx_sm(struct gx_sm_t *sm)
{
   int i;
    sm->state = STATE_INIT;
    sm->tid = 0;//
    sm->events = NULL;
    // pthread_mutex_t p_sm_mtx;
    sm->req_num = 0;
    sm->sess = NULL;

	for(i=0; i<MAX_GY_PORT; i++)
		gy_sess[i] = NULL;
	
	return 0;
}
int free_gx_sm(struct gx_sm_t *sm)
{
	free(sm);

	return 1;
}


int fd_get_session_id(char *src_buf,  char *dst_buf, int flag)
{
        //int len;

        //second_off = strchr(first_off+1, ';');
        //third_off = strchr(second_off+1, ';');
        //len = third_off - second_off -1;

	 //if(flag == 0)
	 /*if(0)
	 {
        	memcpy(dst_buf, second_off+1, len);
        	dst_buf[len] = '\0';
	 }*/

	 if(1)
	 {
        char *first_off;//, *second_off, *third_off;
        first_off = strchr(src_buf, ';');
	 	strcpy(dst_buf, first_off+1);
	 }
	
	return 1;
}


int 	fd_update_cxt_id(int gy_port, char *cxt_value)
{
	_gy_port *gy_port_ptr = NULL;
	
	if((gy_port <0) || (gy_port>=MAX_GY_PORT))
		return 0;

	gy_port_ptr = &gy_space.gy_port[gy_port];
	if (gy_port_ptr->used_flag == 0)
	{
		return 0;
	}

	pthread_mutex_lock(&sess_hash_mutx);
	g_hash_table_remove(g_sess_hash, gy_port_ptr->context_id);// delete hash index
	pthread_mutex_unlock(&sess_hash_mutx);

	strcpy(gy_port_ptr->context_id, cxt_value);

	pthread_mutex_lock(&sess_hash_mutx);
	//g_hash_table_insert(g_sess_hash, strdup(context_id), (gpointer)gy_port_ptr);
	g_hash_table_insert(g_sess_hash, gy_port_ptr->context_id, (gpointer)gy_port_ptr);
	pthread_mutex_unlock(&sess_hash_mutx);

	return 1;
}


/*--------------------------------------------*/

struct gx_sm_t *gl_gx_sm = NULL;

void gx_sig_hdlr()
{
	struct gx_sm_t *gx_sm = gl_gx_sm;

	if( gx_sm)
	{
		// fd_sess_dump( 0 , g_gx_sm.sess);
	 }
	else
	{
		if( NULL != (gx_sm= (struct gx_sm_t *)malloc(sizeof(struct gx_sm_t)) ) )
		{
			init_gx_sm(gx_sm);
		}
		gl_gx_sm = gx_sm;
	}

	gx_send_ccr( &gx_sm, ccr_cmd);
	return;
}


int gx_sig_hdlr_app(_gy_msg *msg_ptr)
{
	struct gx_sm_t *gx_sm = gl_gx_sm;

	if( gx_sm)
	{
		// fd_sess_dump( 0 , g_gx_sm.sess);
	 }
	else
	{
		if( NULL != (gx_sm= (struct gx_sm_t *)malloc(sizeof(struct gx_sm_t)) ) )
		{
			init_gx_sm(gx_sm);
		}
		gl_gx_sm = gx_sm;
	}

	return gx_send_ccr_real( &gx_sm, ccr_cmd, msg_ptr);
}

/* Search a given AVP model in an AVP (extracted from libfreediameter/message.c ) */
int fd_avp_search_avp ( struct avp * groupedavp, struct dict_object * what, struct avp ** avp )
{
	struct avp * nextavp;
	struct avp_hdr * nextavphdr;
	struct dict_avp_data    dictdata;
       
       
	TRACE_ENTRY("%p %p %p", groupedavp, what, avp);

	CHECK_FCT(  fd_dict_getval(what, &dictdata)  );

	// Loop only in the group AVP 
	CHECK_FCT(  fd_msg_browse(groupedavp, MSG_BRW_FIRST_CHILD, (void *)&nextavp, NULL)  );
	CHECK_FCT( fd_msg_avp_hdr( nextavp, &nextavphdr )  );

	while (nextavphdr)
	{
	   
		if ( (nextavphdr->avp_code   == dictdata.avp_code) && (nextavphdr->avp_vendor == dictdata.avp_vendor) ) // always 0 if no Vendor flag
		{
			break;
		}

		// Otherwise move to next AVP in the grouped AVP 
		CHECK_FCT( fd_msg_browse(nextavp, MSG_BRW_NEXT, (void *)&nextavp, NULL) );

		if(nextavp!=NULL)
		{
			CHECK_FCT( fd_msg_avp_hdr( nextavp, &nextavphdr )  );
		}
		else
			nextavphdr=NULL;
	}
	if (avp)
	   *avp = nextavp;

	if (avp && nextavp)
	{
		struct dictionary * dict;
		CHECK_FCT( fd_dict_getdict( what, &dict) );
		CHECK_FCT_DO( fd_msg_parse_dict( nextavp, dict, NULL ),  );
	}
       
	if (avp || nextavp)
		return 0;
	else
		return ENOENT;
}

static int dcca_ans_from_req( struct dict_object * obj, struct msg *qry, struct msg **msg)
{
	struct avp *avp  = NULL;
	struct avp_hdr * avpdata;
	int  rc = -1;

	CHECK_FCT(fd_msg_search_avp( qry, obj, &avp));
	CHECK_FCT(fd_msg_avp_hdr(avp, &avpdata));
	avp = NULL;

	CHECK_FCT_DO( fd_msg_avp_new ( obj, 0, &avp ), goto out  );
	CHECK_FCT_DO( fd_msg_avp_setvalue( avp, avpdata->avp_value ), goto out  );
	CHECK_FCT_DO( fd_msg_avp_add( *msg, MSG_BRW_LAST_CHILD, avp ), goto out  );

	rc = 0;
out:
	return rc;
}
static int gx_parse_cca( struct msg ** msg)
{
	struct msg* cca_msg = *msg;
	struct avp *avp, *grpavp = NULL, *grpavp_sub1 = NULL;
	struct avp_hdr *avphdr;

	char tmp_buf[1024], session_id_str[128];
	_gy_port		*gy_port_ptr = NULL;
	_gy_msg		gy_msg;
	_gy_cca		*cca_ptr = NULL;
	
	LOG_N("fj Parse CCA enter");

	memset(&gy_msg, 0x00, sizeof(_gy_msg));
	memset(session_id_str, 0x00, 128);
	
	cca_ptr = &gy_msg.msg_body.cca;
	gy_msg.msg_type = GY_MSG_CCA;
	/* Session-Id */
	PARSE_AVP_STR(cca_msg, session_id, avp, avphdr, "Parse CCA Session-Id", avphdr->avp_value->os.data)
	if (avphdr != NULL )
		fd_get_session_id((char *)avphdr->avp_value->os.data, session_id_str, 0);
	
	gy_port_ptr = gy_get_port_by_cxt_id(session_id_str);
	if((gy_port_ptr == NULL) || (gy_port_ptr->used_flag == 0))
	{
		if (pps_debug_flag_for_fd())
		{
			sprintf(tmp_buf, "%s, can't find gy_port, cxt_id=%s\r\n", 
				__FUNCTION__, session_id_str);
			pps_debug_info("diameter", tmp_buf);
		}
		
		return 0;
	}

	if (pps_debug_flag_for_fd())
	{
		sprintf(tmp_buf, "\r\n%s, gy_port=%d, app_port=%d, cxt_id=%s\r\n",
			__FUNCTION__, gy_port_ptr->index, gy_port_ptr->app_port, session_id_str);
		pps_debug_info("diameter", tmp_buf);
	}
	
	gy_msg.service_type = gy_port_ptr->service_type;
	gy_msg.app_port = gy_port_ptr->app_port;
	gy_msg.fd_port = gy_port_ptr->index;
	
	/* Origin-Host */
	PARSE_AVP_STR(cca_msg, origin_host, avp, avphdr, "Parse CCA Origin-Host", avphdr->avp_value->os.data)

	/* Origin-Realm */
	PARSE_AVP_STR(cca_msg, origin_realm, avp, avphdr, "Parse CCA Origin-Realm", avphdr->avp_value->os.data)

	/*Destination-Host */
	PARSE_AVP_STR(cca_msg, dest_host, avp, avphdr, "Parse CCA Destination-Host", avphdr->avp_value->os.data)

	/* Destination-Realm */
	PARSE_AVP_STR(cca_msg, dest_realm, avp, avphdr, "Parse CCA Destination-Realm", avphdr->avp_value->os.data)

	/* Auth-Application-Id */
	PARSE_AVP_U32(cca_msg, auth_app_id, avp, avphdr, "Parse CCA Auth-Application-Id", avphdr->avp_value->u32)

	/* CC-Request-Type */
	PARSE_AVP_U32(cca_msg, cc_req_type, avp, avphdr, "Parse CCA CC-Request-Type", avphdr->avp_value->u32)
	if (avphdr != NULL )
		gy_msg.request_type = avphdr->avp_value->u32;
	
	/* CC-Request-Number */
	PARSE_AVP_U32(cca_msg, cc_req_num, avp, avphdr, "Parse CCA CC-Request-Number", avphdr->avp_value->u32)

	/* Result-Code */
	PARSE_AVP_U32(cca_msg, result_code, avp, avphdr, "Parse CCA CC-Result-Code", avphdr->avp_value->u32)
	if (avphdr != NULL )
		cca_ptr->result = avphdr->avp_value->u32;

	/* Multiple-Services-Credit-Control */
	struct dict_object *multiple_services_credit_control = NULL;
	SEARCH_AVP_("Multiple-Services-Credit-Control", 0, &multiple_services_credit_control);		
	CHECK_FCT( fd_msg_search_avp ( cca_msg, multiple_services_credit_control, &grpavp) );
	if(grpavp != NULL)
	{
		LOG_N("fj Parse CCA Multiple-Services-Credit-Control");

             /* Result-Code */
                struct dict_object *result_code = NULL;
                SEARCH_AVP_("Result-Code", 0, &result_code);
		  if(result_code != NULL)
		  {
                	PARSE_GRPAVP_U32(grpavp, result_code, avp, avphdr, "Parse CCA Result-Code", avphdr->avp_value->u32)
			if (avphdr != NULL )
              	  	cca_ptr->result = avphdr->avp_value->u32;
		  }	
		  
		/* Granted-Service-Unit */
		struct dict_object *granted_service_unit = NULL;
		SEARCH_AVP_("Granted-Service-Unit", 0, &granted_service_unit);
		CHECK_FCT( fd_sh_avp_search_avp ( grpavp, granted_service_unit, &grpavp_sub1) );
		if(grpavp_sub1 != NULL)
		{
			/* CC-Time */
			struct dict_object *cc_time = NULL;
			SEARCH_AVP_("CC-Time", 0, &cc_time);
			PARSE_GRPAVP_U32(grpavp_sub1, cc_time, avp, avphdr, "Parse CCA CC-Time", avphdr->avp_value->u32)
			if (avphdr != NULL )
				cca_ptr->grant_value = avphdr->avp_value->u32;
		}
		
		cca_ptr->is_final = 0;

		struct dict_object *final_unit_indication = NULL;
		SEARCH_AVP_("Final-Unit-Indication", 0, &final_unit_indication);
		CHECK_FCT( fd_sh_avp_search_avp ( grpavp, final_unit_indication, &grpavp_sub1) );
		if(grpavp_sub1 != NULL)
		{
			/* Final-Unit-Action */
			struct dict_object *final_unit_action= NULL;
			SEARCH_AVP_("Final-Unit-Action", 0, &final_unit_action);
			PARSE_GRPAVP_U32(grpavp_sub1, final_unit_action, avp, avphdr, "Parse CCA Final-Unit-Action", avphdr->avp_value->u32)
			if (avphdr != NULL )
				cca_ptr->is_final = 1;
		}

		/*
		struct dict_object *final_unit_indication = NULL;
		SEARCH_AVP_("Final-Unit-Indication", 0, &final_unit_indication);
		if(final_unit_indication != NULL)
		{
			PARSE_GRPAVP_U32(grpavp, final_unit_indication, avp, avphdr, "Parse CCA Final-Unit-Indication", avphdr->avp_value->u32)	
			
			cca_ptr->is_final = avphdr->avp_value->u32;
			if(cca_ptr->is_final>1)
				cca_ptr->is_final = 0;
				
		}
		*/
	}

	//pps_recv_gy_process(&gy_msg);
	pps_ro_gy_cb(&gy_msg);
	/*pthread_mutex_lock( &gy_msg_mtx );
	gx_add_msg_to_list(&gy_msg);
	pthread_mutex_unlock( &gy_msg_mtx );*/

	gx_stat_increase_recv_cca(gy_msg.request_type);
	
	if(gy_msg.request_type == RT_TERMINATE_REQUEST ||
		gy_msg.request_type == RT_EVENT_REQUEST ||
		(cca_ptr->result != 2001 && gy_msg.request_type != RT_UPDATE_REQUEST))
	{
		unsigned int gy_port;

		gy_port = gy_port_ptr->index;
		if(gy_port < MAX_GY_PORT)
		{
			gy_release_port(gy_port);
			if(gy_sess[gy_port] != NULL)
				fd_sess_destroy(&gy_sess[gy_port]);
		}
	}
out:
	LOG_N("fj Parse CCA exit");
	return 0;
}


static int gx_parse_ccr( struct msg ** msg, struct gy_msg *gy_ptr)
{
	struct msg* ccr_msg = *msg;
	struct avp *avp, *groupedavp=NULL, *groupedavp_sub=NULL, *groupedavp_sub_sub=NULL;
	struct avp_hdr *avphdr;
	struct gy_ccr    *gy_ccr = NULL;
	int len;
	
	// struct dict_object *dict_obj_tmp = NULL;

	LOG_N("fj Parse CCR enter");

	gy_ccr = &gy_ptr->msg_body.ccr;
	
	/* Session-Id */
	PARSE_AVP_STR(ccr_msg, session_id, avp, avphdr, "Parse CCR Session-Id", avphdr->avp_value->os.data)
	{
		//char padding[12]={";CCR_SESS"};
		char sess_id[128];
		
		//sprintf(sess_id, "%s%s",avphdr->avp_value->os.data, padding);
		if (avphdr != NULL)
		{
			if (avphdr->avp_value->os.len >= 128)
			{
				avphdr->avp_value->os.len = 127;
			}
			memcpy(sess_id, avphdr->avp_value->os.data, avphdr->avp_value->os.len);
			sess_id[avphdr->avp_value->os.len] = '\0';
			//sprintf(sess_id, "%s",avphdr->avp_value->os.data);
			//fd_get_session_id(sess_id, gy_ptr->cxt_id, 0);
			strcpy(gy_ptr->cxt_id, sess_id);
		}
	}
	
	/* Origin-Host */
	PARSE_AVP_STR(ccr_msg, origin_host, avp, avphdr, "Parse CCR Origin-Host", avphdr->avp_value->os.data)
	if (avphdr != NULL)
	{
		if (avphdr->avp_value->os.len >= GY_APN_LEN)
		{
			avphdr->avp_value->os.len = GY_APN_LEN-1;
		}
		memcpy(gy_ccr->apn, avphdr->avp_value->os.data, avphdr->avp_value->os.len);
		gy_ccr->apn[avphdr->avp_value->os.len] = '\0';
	}
	
	/* Origin-Realm */
	PARSE_AVP_STR(ccr_msg, origin_realm, avp, avphdr, "Parse CCR Origin-Realm", avphdr->avp_value->os.data)

	/*Destination-Host */
	PARSE_AVP_STR(ccr_msg, dest_host, avp, avphdr, "Parse CCR Destination-Host", avphdr->avp_value->os.data)

	/* Destination-Realm */
	PARSE_AVP_STR(ccr_msg, dest_realm, avp, avphdr, "Parse CCR Destination-Realm", avphdr->avp_value->os.data)

	/* Auth-Application-Id */
	PARSE_AVP_U32(ccr_msg, auth_app_id, avp, avphdr, "Parse CCR Auth-Application-Id", avphdr->avp_value->u32)

	/* Service-Context-Id */
	PARSE_AVP_STR(ccr_msg, service_cxt_id, avp, avphdr, "Parse CCR Service-Context-Id", avphdr->avp_value->os.data)
	
	/* CC-Request-Type */
	PARSE_AVP_U32(ccr_msg, cc_req_type, avp, avphdr, "Parse CCR CC-Request-Type", avphdr->avp_value->u32)
	if (avphdr != NULL)
	{
		gy_ptr->request_type = avphdr->avp_value->u32;
	}

	/* Requested-Action */
	PARSE_AVP_U32(ccr_msg, requested_action, avp, avphdr, "Parse CCR Requested-Action", avphdr->avp_value->u32)
	if (avphdr != NULL)
	{
		gy_ptr->msg_body.ccr.request_action = avphdr->avp_value->u32;
	}
	
	/* CC-Request-Number */
	PARSE_AVP_U32(ccr_msg, cc_req_num, avp, avphdr, "Parse CCR CC-Request-Number", avphdr->avp_value->u32)
	if (avphdr != NULL)
	{
		gy_ptr->request_number = avphdr->avp_value->u32;
	}

	/* Requested-Service-Unit */
	CHECK_FCT( fd_msg_search_avp ( ccr_msg, requested_service_unit, &groupedavp) );
	if(groupedavp != NULL)
	{
		LOG_N("fj Parse CCR Requested-Service-Unit");

		/* CC-Money */
		struct dict_object *cc_money = NULL;
		SEARCH_AVP_("CC-Money", 0, &cc_money);
		CHECK_FCT( fd_sh_avp_search_avp ( groupedavp, cc_money, &groupedavp_sub) );
		if(groupedavp_sub != NULL)
		{
			/* Unit-Value */
			struct dict_object *unit_value = NULL;
			SEARCH_AVP_("Unit-Value", 0, &unit_value);
			CHECK_FCT( fd_sh_avp_search_avp ( groupedavp_sub, unit_value, &groupedavp_sub_sub));
			if(groupedavp_sub_sub != NULL)
			{
				/* Value-Digits */
				struct dict_object *value_digits = NULL;
				SEARCH_AVP_("Value-Digits", 0, &value_digits);	
				avphdr = NULL;
				PARSE_GRPAVP_U64(groupedavp_sub_sub, value_digits, avp, avphdr, "Parse CCR value-digits", avphdr->avp_value->u64)
				if (avphdr != NULL)
				{
					gy_ptr->msg_body.ccr.req_service_unit = avphdr->avp_value->u64;
				}

				/* Exponent */
				struct dict_object *exponent = NULL;
				SEARCH_AVP_("Exponent", 0, &exponent);
				avphdr = NULL;
				PARSE_GRPAVP_U32(groupedavp_sub_sub, exponent, avp, avphdr, "Parse CCR Exponent", avphdr->avp_value->i32)
				if ((avphdr != NULL) && (avphdr->avp_value->i32 != 0))
				{
					gy_ptr->msg_body.ccr.req_service_unit *= pow(10, avphdr->avp_value->i32);
				}
			}
		}
	}

	/* Event-Timestamp */
	PARSE_AVP_STR(ccr_msg, event_timestamp, avp, avphdr, "Parse CCR Event-Timestamp", avphdr->avp_value->os.data)

	/* Subscription-Id */
	CHECK_FCT( fd_msg_search_avp ( ccr_msg, subscription_id, &groupedavp) );
	if(groupedavp != NULL)
	{
		LOG_N("fj Parse CCR Subscription-Id");

		/* Subscription-Id-Type */
		SEARCH_AVP_("Subscription-Id-Type", 0, &subscription_id_type);
		PARSE_GRPAVP_U32(groupedavp, subscription_id_type, avp, avphdr, "Parse CCR Subscription-Id-Type", avphdr->avp_value->u32)

		/* Subscription-Id-Data */
		SEARCH_AVP_("Subscription-Id-Data", 0, &subscription_id_data);
		PARSE_GRPAVP_STR(groupedavp, subscription_id_data, avp, avphdr, "Parse CCR Subscription-Id-Data", avphdr->avp_value->os.data)
		if(avphdr != NULL )
		{
			if(avphdr->avp_value != NULL)
			{
				if(avphdr->avp_value->os.data != NULL)
				{
					if(strlen((char *)avphdr->avp_value->os.data) >= NUMBER_LEN)
					{
						memcpy(gy_ccr->caller, avphdr->avp_value->os.data, NUMBER_LEN - 1);
						gy_ccr->caller[NUMBER_LEN-1] = '\0';
					}
					else
						strcpy(gy_ccr->caller, (char *)avphdr->avp_value->os.data);
				}
			}
		}		
	}

	gy_ptr->service_type = ST_PS_DATA;

	/* Service-Information */
	CHECK_FCT( fd_msg_search_avp ( ccr_msg, service_information, &groupedavp) );
	if(groupedavp != NULL)
	{
		LOG_N("fj Parse CCR Service-Information");

		/* Value-Digits */
		/*struct dict_object *value_digits = NULL;
		SEARCH_AVP_("Value-Digits", 0, &value_digits);
		avphdr = NULL;
		PARSE_GRPAVP_U64(groupedavp, value_digits, avp, avphdr, "Parse CCR value_digits", avphdr->avp_value->u64)
		if (avphdr != NULL)
		{
			gy_ptr->msg_body.ccr.balance_to_check = avphdr->avp_value->u64;
		}*/
		
		/* IMS-Information */
		SEARCH_AVP_("IMS-Information", 10415, &ims_information);
		CHECK_FCT( fd_sh_avp_search_avp ( groupedavp, ims_information, &groupedavp_sub) );
		if(groupedavp_sub == NULL)
		{
			gy_ptr->service_type = ST_PS_DATA;

			/* PS-Information */
			SEARCH_AVP_("PS-Information", 10415, &ps_information);
			CHECK_FCT( fd_sh_avp_search_avp ( groupedavp, ps_information, &groupedavp_sub) );
			if(groupedavp_sub != NULL)
			{
				gy_ptr->service_type = ST_PS_DATA;

				/* SGSN-Address */
				struct dict_object *sgsn_address = NULL;
				SEARCH_AVP_("SGSN-Address", 10415, &sgsn_address);
				PARSE_GRPAVP_STR(groupedavp_sub, sgsn_address, avp, avphdr, "Parse CCR SGSN-Address", avphdr->avp_value->os.data)
				if(avphdr != NULL )
				{
					if(avphdr->avp_value != NULL)
					{
						if(avphdr->avp_value->os.data != NULL)
						{
							memcpy(&gy_ptr->msg_body.ccr.sgsn_ip, &avphdr->avp_value->os.data[2], 4);					
						}
					}
				}		


				/* GGSN-Address */
				struct dict_object *ggsn_address = NULL;
				SEARCH_AVP_("GGSN-Address", 10415, &ggsn_address);
				PARSE_GRPAVP_U32(groupedavp_sub, ggsn_address, avp, avphdr, "Parse CCR GGSN-Address", avphdr->avp_value->u32)
				if(avphdr != NULL )
				{
					if(avphdr->avp_value != NULL)
					{
						if(avphdr->avp_value->os.data != NULL)
						{
							memcpy(&gy_ptr->msg_body.ccr.ggsn_ip, &avphdr->avp_value->os.data[2], 4);					
						}
					}
				}		

			}
			else
			{
				/* SMS-Information */
				SEARCH_AVP_("SMS-Information", 10415, &sms_information);
				CHECK_FCT( fd_sh_avp_search_avp ( groupedavp, sms_information, &groupedavp_sub) );
				if(groupedavp_sub != NULL)
				{
					gy_ptr->service_type = ST_CS_SMS;

					/* Recipient-Info */
					struct dict_object *recipient_info = NULL;
					SEARCH_AVP_("Recipient-Info", 10415, &recipient_info);
					CHECK_FCT( fd_sh_avp_search_avp ( groupedavp_sub, recipient_info, &groupedavp_sub_sub) );
					if (groupedavp_sub_sub != NULL)
					{
						/* Recipient-Address */
						struct avp *grp_sub = NULL;
						struct dict_object *recipient_addr = NULL;
						SEARCH_AVP_("Recipient-Address", 10415, &recipient_addr);
						CHECK_FCT( fd_sh_avp_search_avp ( groupedavp_sub_sub, recipient_addr, &grp_sub) );
						if (grp_sub != NULL)
						{
							/* Address-Data */
							struct dict_object *address_data = NULL;
							SEARCH_AVP_("Address-Data", 10415, &address_data);
							avphdr = NULL;
							PARSE_GRPAVP_STR(grp_sub, address_data, avp, avphdr, "Parse CCR Address-Data", avphdr->avp_value->os.data)
							if(avphdr != NULL )
							{
								if(avphdr->avp_value != NULL)
								{
									if(avphdr->avp_value->os.data != NULL)
									{
										int len = avphdr->avp_value->os.len;
										if (len >= NUMBER_LEN)
										{
											len = NUMBER_LEN-1;
										}
										
										memcpy(&gy_ccr->called, &avphdr->avp_value->os.data[0], len);
										gy_ccr->called[len] = '\0';
									}
								}
							}
						}
					}

					/* Number-of-Messages-Sent */
					struct dict_object *num_msg_sent = NULL;
					SEARCH_AVP_("Number-Of-Messages-Sent", 10415, &num_msg_sent);
					avphdr = NULL;
					PARSE_GRPAVP_U32(groupedavp_sub, num_msg_sent, avp, avphdr, "Parse CCR Number-Of-Messages-Sent", avphdr->avp_value->u32)
					if((avphdr != NULL) && (avphdr->avp_value != NULL))
					{
						gy_ccr->sent_msg_num = avphdr->avp_value->u32;
					}

					/* SMSC-Address */
					struct dict_object *smsc_address = NULL;
					SEARCH_AVP_("SMSC-Address", 10415, &smsc_address);
					avphdr = NULL;
					PARSE_GRPAVP_STR(groupedavp_sub, smsc_address, avp, avphdr, "Parse CCR SMSC-Address", avphdr->avp_value->os.data)
					if(avphdr != NULL )
					{
						if(avphdr->avp_value != NULL)
						{
							if((avphdr->avp_value->os.data != NULL) && (avphdr->avp_value->os.len > 2))
							{
								int len = avphdr->avp_value->os.len - 2;
								if (len >= NUMBER_LEN)
								{
									len = NUMBER_LEN-1;
								}
								
								memcpy(&gy_ccr->smsc, &avphdr->avp_value->os.data[2], len);
								gy_ccr->smsc[len] = '\0';
							}
						}
					}
				}
			}
		}
		else if(groupedavp_sub != NULL)
		{
			gy_ptr->service_type = ST_CS_VOICE;

			/* Node-Functionality */
			struct dict_object *node_functionality = NULL;
			SEARCH_AVP_("Node-Functionality", 10415, &node_functionality);
			PARSE_GRPAVP_U32(groupedavp_sub, node_functionality, avp, avphdr, "Parse CCR Node-Functionality", avphdr->avp_value->u32)

			/* Event-Type */
			struct dict_object *event_type = NULL;
			SEARCH_AVP_("Event-Type", 10415, &event_type);
			CHECK_FCT( fd_sh_avp_search_avp ( groupedavp_sub, event_type, &groupedavp_sub_sub) );
			if(groupedavp_sub_sub != NULL)
			{
				/* SIP-Method */
				struct dict_object *sip_method = NULL;
				SEARCH_AVP_("SIP-Method", 10415, &sip_method);	
				PARSE_GRPAVP_STR(groupedavp_sub_sub, sip_method, avp, avphdr, "Parse CCR Parse CCR SIP-Method", avphdr->avp_value->os.data)
			}

			/* Role-of-Node */
			struct dict_object *role_of_node = NULL;
			SEARCH_AVP_("Role-of-Node", 10415, &role_of_node);		
			PARSE_GRPAVP_U32(groupedavp_sub, role_of_node, avp, avphdr, "Parse CCR Role-of-Node", avphdr->avp_value->u32)
			if (avphdr != NULL)
			{
				gy_ptr->msg_body.ccr.role_of_node = avphdr->avp_value->u32;
			}
			
			/* User-Session-Id */
			struct dict_object *user_session_id = NULL;
			SEARCH_AVP_("User-Session-Id", 10415, &user_session_id);		
			PARSE_GRPAVP_STR(groupedavp_sub, user_session_id, avp, avphdr, "Parse CCR User-Session-Id", avphdr->avp_value->os.data)
	
			/* Time-Stamps */
			struct dict_object *time_stamps = NULL;
			SEARCH_AVP_("Time-Stamps", 10415, &time_stamps);
			CHECK_FCT( fd_sh_avp_search_avp ( groupedavp_sub, time_stamps, &groupedavp_sub_sub) );
			if(groupedavp_sub_sub != NULL)
			{
				/* SIP-Request-Timestamp */
				struct dict_object *sip_request_timestamp = NULL;
				SEARCH_AVP_("SIP-Request-Timestamp", 10415, &sip_request_timestamp);
				PARSE_GRPAVP_STR(groupedavp_sub_sub, sip_request_timestamp, avp, avphdr, "Parse CCR SIP-Request-Timestamp", avphdr->avp_value->os.data)
	
				/*SIP-Response-Timestamp */
				struct dict_object *sip_response_timestamp = NULL;
				SEARCH_AVP_("SIP-Response-Timestamp", 10415, &sip_response_timestamp);
				PARSE_GRPAVP_STR(groupedavp_sub_sub, sip_response_timestamp, avp, avphdr, "Parse CCR SIP-Response-Timestamp", avphdr->avp_value->os.data)
			}
	
			/*Inter-Operator-Identifier */
			struct dict_object *inter_operator_identifier = NULL;
			SEARCH_AVP_("Inter-Operator-Identifier", 10415, &inter_operator_identifier);
			CHECK_FCT( fd_sh_avp_search_avp ( groupedavp_sub, inter_operator_identifier, &groupedavp_sub_sub) );
			if(groupedavp_sub_sub != NULL)
			{
				/* Originating-IOI */
				struct dict_object *originating_ioi = NULL;
				SEARCH_AVP_("Originating-IOI", 10415, &originating_ioi);
				PARSE_GRPAVP_STR(groupedavp_sub_sub, originating_ioi, avp, avphdr, "Parse CCR Originating-IOI", avphdr->avp_value->os.data)
	
				/* Terminating-IOI */
				struct dict_object *terminating_ioi = NULL;
				SEARCH_AVP_("Terminating-IOI", 10415, &terminating_ioi);
				PARSE_GRPAVP_STR(groupedavp_sub_sub, terminating_ioi, avp, avphdr, "Parse CCR Terminating-IOI", avphdr->avp_value->os.data)
			}
	
			/* IMS-Charging-Identifier */
			struct dict_object *ims_charging_dentifier = NULL;
			SEARCH_AVP_("IMS-Charging-Identifier", 10415, &ims_charging_dentifier); 	
			PARSE_GRPAVP_STR(groupedavp_sub, ims_charging_dentifier, avp, avphdr, "Parse CCR IMS-Charging-Identifier", NULL/*avphdr->avp_value->os.data*/)
	
			/* SDP-Session-Description */
			struct dict_object *sdp_session_description = NULL;
			SEARCH_AVP_("SDP-Session-Description", 10415, &sdp_session_description);		
			PARSE_GRPAVP_STR(groupedavp_sub, sdp_session_description, avp, avphdr, "Parse CCR SDP-Session-Description", NULL/*avphdr->avp_value->os.data*/)
	
			/* SDP-Media-Component */
			struct dict_object *sdp_media_component = NULL;
			SEARCH_AVP_("SDP-Media-Component", 10415, &sdp_media_component);
			CHECK_FCT( fd_sh_avp_search_avp ( groupedavp_sub, sdp_media_component, &groupedavp_sub_sub) );
			if(groupedavp_sub_sub != NULL)
			{
				/* SDP-Media-Name */
				struct dict_object *sdp_media_name = NULL;
				SEARCH_AVP_("SDP-Media-Name", 10415, &sdp_media_name);
				PARSE_GRPAVP_STR(groupedavp_sub_sub, sdp_media_name, avp, avphdr, "Parse CCR SDP-Media-Name", NULL/*avphdr->avp_value->os.data*/)
	
				/* SDP-Media-Description */
				struct dict_object *sdp_media_description = NULL;
				SEARCH_AVP_("SDP-Media-Description", 10415, &sdp_media_description);
				PARSE_GRPAVP_STR(groupedavp_sub_sub, sdp_media_description, avp, avphdr, "Parse CCR SDP-Media-Description", NULL/*avphdr->avp_value->os.data*/)
			}
	
			/* Message-Body */
			struct dict_object *message_body = NULL;
			SEARCH_AVP_("Message-Body", 10415, &message_body);
			CHECK_FCT( fd_sh_avp_search_avp ( groupedavp_sub, message_body, &groupedavp_sub_sub) );
			if(groupedavp_sub_sub != NULL)
			{
				/* Content-Type */
				struct dict_object *content_type = NULL;
				SEARCH_AVP_("Content-Type", 10415, &content_type);
				PARSE_GRPAVP_STR(groupedavp_sub_sub, content_type, avp, avphdr, "Parse CCR Content-Type", NULL/*avphdr->avp_value->os.data*/)
	
				/* Content-Length */
				struct dict_object *content_length = NULL;
				SEARCH_AVP_("Content-Length", 10415, &content_length);
				PARSE_GRPAVP_U32(groupedavp_sub_sub, content_length, avp, avphdr, "Parse CCR Content-Length", avphdr->avp_value->u32)
			}
	
			/* Access-Network-Information */
			struct dict_object *access_network_information = NULL;
			SEARCH_AVP_("Access-Network-Information", 10415, &access_network_information);		
			PARSE_GRPAVP_STR(groupedavp_sub, access_network_information, avp, avphdr, "Parse CCR Access-Network-Information", NULL/*avphdr->avp_value->os.data*/)
	
			/* Calling-Party-Address */
			struct dict_object *calling_party_address = NULL;
			SEARCH_AVP_("Calling-Party-Address", 10415, &calling_party_address);		
			PARSE_GRPAVP_STR(groupedavp_sub, calling_party_address, avp, avphdr, "Parse CCR Calling-Party-Address", NULL/*avphdr->avp_value->os.data*/)
			if (avphdr != NULL &&  avphdr->avp_value != NULL)
			{
				if( avphdr->avp_value->os.data != NULL)
				{
				       len = strlen((char *)avphdr->avp_value->os.data);
					if(len>NUMBER_LEN) len = NUMBER_LEN;
					memcpy(gy_ccr->caller, avphdr->avp_value->os.data, len);
				}
			}
			
			/* Called-Party-Address */
			struct dict_object *called_party_address = NULL;
			SEARCH_AVP_("Called-Party-Address", 10415, &called_party_address);		
			PARSE_GRPAVP_STR(groupedavp_sub, called_party_address, avp, avphdr, "Parse CCR Called-Party-Address", avphdr->avp_value->os.data)
			if (avphdr != NULL &&  avphdr->avp_value != NULL)
			{
				if(avphdr->avp_value->os.data != NULL)
				{
				       len = strlen((char *)avphdr->avp_value->os.data);
					if(len>NUMBER_LEN) len = NUMBER_LEN;

					memcpy(gy_ccr->called, avphdr->avp_value->os.data, len);
					gy_ptr->service_type = ST_CS_VOICE;
				}
			}
			
			/* Requested-Party-Address */
			struct dict_object *requested_party_address = NULL;
			SEARCH_AVP_("Requested-Party-Address", 10415, &requested_party_address);		
			PARSE_GRPAVP_STR(groupedavp_sub, requested_party_address, avp, avphdr, "Parse CCR Requested-Party-Address", avphdr->avp_value->os.data)
	
			/* huawei_avp_20820 */
			struct dict_object *huawei_avp_20820 = NULL;
			SEARCH_AVP_("huawei_avp_20820", 2011, &huawei_avp_20820);		
			PARSE_GRPAVP_U32(groupedavp_sub, huawei_avp_20820, avp, avphdr, "Parse CCR huawei_avp_20820", avphdr->avp_value->u32)
	
			/* Subscription-Id-Type */
			PARSE_GRPAVP_U32(groupedavp_sub, subscription_id_type, avp, avphdr, "Parse CCR Subscription-Id-Type", avphdr->avp_value->u32)
	
			/* IMS-Information */
			PARSE_GRPAVP_STR(groupedavp_sub, subscription_id_data, avp, avphdr, "Parse CCR Parse CCR IMS-Information", avphdr->avp_value->os.data)
//			if(strlen(avphdr->avp_value->os.data))
//				strcpy(gy_ccr->caller, avphdr->avp_value->os.data);
		}
	}

	/* Service-Identifier */
	PARSE_AVP_U32(ccr_msg, service_identifier, avp, avphdr, "Parse CCR Service-Identifier", avphdr->avp_value->u32)

	/* Multiple-Services-Indicator */
	PARSE_AVP_U32(ccr_msg, multiple_services_indicator, avp, avphdr, "Parse CCR Multiple-Services-Indicator", avphdr->avp_value->u32)

	/* Multiple-Services-Credit-Control */
	//gy_ptr->msg_body.ccr.mscc_presented = 0;
	struct dict_object *multiple_services_credit_control = NULL;
	SEARCH_AVP_("Multiple-Services-Credit-Control", 0, &multiple_services_credit_control);		
	CHECK_FCT( fd_msg_search_avp ( ccr_msg, multiple_services_credit_control, &groupedavp) );
	gy_ptr->rating_group = 100;// init to 100(huawei PNCC)
	gy_ptr->service_identifier = -1;// init to -1(invalid, huawei PNCC)
	gy_ptr->msg_body.ccr.reporting_reason = -1;// init to -1
	if(groupedavp != NULL)
	{
		LOG_N("fj Parse CCR Multiple-Services-Credit-Control");

		//gy_ptr->msg_body.ccr.mscc_presented = 1;
		/* Requested-Service-Unit */
		struct dict_object *requested_service_unit = NULL;
		SEARCH_AVP_("Requested-Service-Unit", 0, &requested_service_unit);
		CHECK_FCT( fd_sh_avp_search_avp ( groupedavp, requested_service_unit, &groupedavp_sub) );
		if(groupedavp_sub != NULL)
		{
			/* CC-Time */
			/*struct dict_object *cc_time = NULL;
			SEARCH_AVP_("CC-Time", 0, &cc_time);
			PARSE_GRPAVP_U32(groupedavp_sub, cc_time, avp, avphdr, "Parse CCR CC-Time", avphdr->avp_value->u32)*/
		}

		/* Used-Service-Unit */
		struct dict_object *used_service_unit = NULL;
		SEARCH_AVP_("Used-Service-Unit", 0, &used_service_unit);
		CHECK_FCT( fd_sh_avp_search_avp ( groupedavp, used_service_unit, &groupedavp_sub) );
		if(groupedavp_sub != NULL)
		{
			if(gy_ptr->service_type == ST_CS_VOICE)
			{
				/* CC-Time */
				struct dict_object *cc_time = NULL;
				SEARCH_AVP_("CC-Time", 0, &cc_time);
				PARSE_GRPAVP_U32(groupedavp_sub, cc_time, avp, avphdr, "Parse CCR CC-Time", avphdr->avp_value->u32)
				if (avphdr != NULL)
				{
					gy_ptr->msg_body.ccr.used_unit = avphdr->avp_value->u32;
				}
			}
			else if(gy_ptr->service_type == ST_PS_DATA)
			{
				/* CC-Total-Octets */	
				struct dict_object *cc_total_octets = NULL;
				SEARCH_AVP_("CC-Total-Octets", 0, &cc_total_octets);		
				PARSE_GRPAVP_U32(groupedavp_sub, cc_total_octets, avp, avphdr, "Parse CCR CC-Total-Octets", avphdr->avp_value->u32)
				if (avphdr != NULL)
				{
					gy_ptr->msg_body.ccr.used_unit = avphdr->avp_value->u32;
				}

				/* Reporting-Reason */
				struct dict_object *reporting_reason = NULL;
				avphdr = NULL;
				SEARCH_AVP_("Reporting-Reason", 10415, &reporting_reason);
				PARSE_GRPAVP_U32(groupedavp_sub, reporting_reason, avp, avphdr, "Parse CCR Reporting-Reason", avphdr->avp_value->u32)
				if (avphdr != NULL)
				{
					gy_ptr->msg_body.ccr.reporting_reason = avphdr->avp_value->u32;
				}
			}
			
		}

		/* Service-Identifier */
		struct dict_object *service_id = NULL;
		avphdr = NULL;
		SEARCH_AVP_("Service-Identifier", 0, &service_id);
		PARSE_GRPAVP_U32(groupedavp, service_id, avp, avphdr, "Parse CCR Service-Identifier", avphdr->avp_value->u32)
		if (avphdr != NULL)
		{
			gy_ptr->service_identifier = avphdr->avp_value->u32;
		}

		/* Rating-Group */
		struct dict_object *rating_group = NULL;
		avphdr = NULL;
		SEARCH_AVP_("Rating-Group", 0, &rating_group);		
		PARSE_GRPAVP_U32(groupedavp, rating_group, avp, avphdr, "Parse CCR Rating-Group", avphdr->avp_value->u32)
		if (avphdr != NULL)
		{
			gy_ptr->rating_group = avphdr->avp_value->u32;
		}

		/* Reporting-Reason */
		struct dict_object *reporting_reason = NULL;
		avphdr = NULL;
		SEARCH_AVP_("Reporting-Reason", 10415, &reporting_reason);
		PARSE_GRPAVP_U32(groupedavp, reporting_reason, avp, avphdr, "Parse CCR Reporting-Reason", avphdr->avp_value->u32)
		//if (avphdr != NULL)
		//{
		//	gy_ptr->msg_body.ccr.reporting_reason = avphdr->avp_value->u32;
		//}
	}
	
//	strcpy(gy_ptr->cxt_id, gy_ccr->caller);
out:
	LOG_N("fj Parse CCR exit");
	return 0;
}

struct msg *g_direct_cca_fail_msg_ptr = NULL;
struct msg *g_ccr_msg_ptr[MAX_GY_PORT+1];
struct msg *g_ccr_msg_ptr_ptr[MAX_GY_PORT+1];
int gx_send_cca_test()
{
	struct msg *ans;
	struct avp *avp = NULL;
	struct avp *grpavp = NULL;
	struct avp *grpavp_sub1 = NULL;
	union avp_value val;
	//struct dict_object *dict_obj_tmp = NULL;

	ans = g_ccr_msg_ptr[0];
	
	/* set application id */
	{
		struct msg_hdr * msg_hdr = NULL;
		ASSERT( 0 == fd_msg_hdr ( ans, &msg_hdr ) );
		msg_hdr->msg_appl = SH_APP_ID;
		msg_hdr->msg_flags = msg_hdr->msg_flags & (~CMD_FLAG_PROXIABLE);

	}

	/* Set the Origin-Host, Origin-Realm, Result-Code AVPs */
	CHECK_FCT_DO( fd_msg_rescode_set( ans, "DIAMETER_SUCCESS", NULL, NULL, 1 ), goto out );

	/* Get the auth_app_id and from the reply and set it in the reply */
	EN_AVP_U32(auth_app_id, 4, ans, "fj CCA Auth-Application-ID");
	EN_AVP_U32(cc_req_type, 1, ans, "fj CCA cc_req_type");
	EN_AVP_U32(cc_req_num, 0, ans, "fj CCA cc_req_num");
	
	/* Multiple-Services-Credit-Control */
	{
		CHECK_FCT_DO( fd_msg_avp_new ( multiple_services_credit_control, 0, &grpavp ), goto out  );

		/* Result-Code */
		struct dict_object *result_code = NULL;
		EN_GRPAVP_U32("Result-Code", 0, result_code, 2001);
		
		/* Granted-Service-Unit */
		struct dict_object *granted_service_unit = NULL;
		SEARCH_AVP_("Granted-Service-Unit", 0, &granted_service_unit);
		{
			CHECK_FCT_DO( fd_msg_avp_new ( granted_service_unit, 0, &grpavp_sub1 ), goto out  );
		
			EN_GRPAVP_U32_("CC-Time", 0, cc_time, 1/*granted_value*/, grpavp_sub1)

			CHECK_FCT_DO( fd_msg_avp_add( grpavp, MSG_BRW_LAST_CHILD, grpavp_sub1 ), goto out  );
			
			LOG_D("fj CCA Granted-Service-Unit Ok\n");
		}

		CHECK_FCT_DO( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, grpavp ), goto out  );
		
		LOG_D("fj CCA Multiple-Services-Credit-Control Ok\n");
	}

	/* Send the answer */
	CHECK_FCT_DO( fd_msg_send((struct msg **)(g_ccr_msg_ptr_ptr), NULL, NULL ), goto out );
	
out:
	return 1;
}

int gx_send_cca(_gy_msg *gy_ptr)
{
	//struct msg *req = NULL;
	struct msg *ans;//, *qry;
	struct avp *avp = NULL;
	struct avp *grpavp = NULL;
	struct avp *grpavp_sub1 = NULL;
	union avp_value val;
	//struct dict_object *dict_obj_tmp = NULL;
	struct msg **pAnsPtr = NULL;
	//int ret;

	long	granted_value = gy_ptr->msg_body.cca.grant_value;
	int	port = gy_ptr->fd_port;
	_gy_port 	*gy_port = NULL;
	long valid_time_len = 900;
	
	gy_port = gy_get_port_space(port);
	if(gy_port == NULL)
		return 0;
	gy_port->app_port = gy_ptr->app_port;

	gy_port->updated_ts = ts_sec;

	if (pps_debug_flag_for_fd())
	{
		char tmp_buf[256];
		sprintf(tmp_buf, " [%04d] %s ,  app_port=%d, gy_port=%d", 
			port, __FUNCTION__, gy_ptr->app_port, gy_port->index);
		pps_debug_info("diameter", tmp_buf);
	}

	gx_stat_increase_send_cca(gy_ptr->request_type);
	
	ans = g_ccr_msg_ptr[port];

	//memset(ans, 0x00, sizeof(ans));
//	CHECK_FCT_DO( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, &ans, 0 ) , goto out);
	
	/* set application id */
	{
		struct msg_hdr * msg_hdr = NULL;
		ASSERT( 0 == fd_msg_hdr ( ans, &msg_hdr ) );
		msg_hdr->msg_appl = SH_APP_ID;
		msg_hdr->msg_flags = msg_hdr->msg_flags | (CMD_FLAG_PROXIABLE);
	}

	/* Set the Origin-Host, Origin-Realm, Result-Code AVPs */
	if (gy_ptr->request_type == RT_EVENT_REQUEST)
	{
		EN_AVP_U32(result_code, gy_ptr->msg_body.cca.result, ans, "fj CCA Result-Code");
	}
	/*else if (gy_ptr->msg_body.ccr.mscc_presented==0)
	{
        int result = gy_ptr->msg_body.cca.result;
        if (result < 2001)
        {
            result = 2001;
        }
        else if (resutl == 4012)
        {
            result = 4547;
        }
        else if (resutl != 2001)
        {
            result = 5012;
        }
		EN_AVP_U32(result_code, result, ans, "fj CCA Result-Code");
	}*/
    else
	{
		CHECK_FCT_DO( fd_msg_rescode_set( ans, "DIAMETER_SUCCESS", NULL, NULL, 1 ), goto out );
	}

	/* Get the auth_app_id and from the reply and set it in the reply */
	EN_AVP_U32(auth_app_id, 4, ans, "fj CCA Auth-Application-ID");
	EN_AVP_U32(cc_req_type, gy_ptr->request_type, ans, "fj CCA cc_req_type");
	EN_AVP_U32(cc_req_num, gy_port->request_number++, ans, "fj CCA cc_req_num");

	if (gy_ptr->request_type == RT_EVENT_REQUEST)
	{
		if ((gy_ptr->msg_body.ccr.request_action == RA_CHECK_BALANCE)\
			&& (gy_ptr->msg_body.cca.result == 2001))// only support CHECK_BALANCE in event request
		{
			EN_AVP_U32(check_balance_result, gy_ptr->msg_body.cca.check_balance_result, ans, "fj CCA check_balance_result");
		}
	}
	else// if (gy_ptr->msg_body.ccr.mscc_presented)
	/* Multiple-Services-Credit-Control */
	{
		CHECK_FCT_DO( fd_msg_avp_new ( multiple_services_credit_control, 0, &grpavp ), goto out  );

		/* Result-Code */
		struct dict_object *result_code = NULL;
		if(gy_ptr->msg_body.cca.result < 2001)
			gy_ptr->msg_body.cca.result = 2001;		
		EN_GRPAVP_U32("Result-Code", 0, result_code, gy_ptr->msg_body.cca.result); 

		if(gy_ptr->msg_body.cca.is_final && gy_ptr->msg_body.cca.result == 2001) //only successful result can contain this AVP
		{
			struct dict_object *final_unit_indication = NULL;
			SEARCH_AVP_("Final-Unit-Indication", 0, &final_unit_indication);
			{
				CHECK_FCT_DO( fd_msg_avp_new ( final_unit_indication, 0, &grpavp_sub1 ), goto out  );
			
				EN_GRPAVP_U32_("Final-Unit-Action", 0, final_unit_action, 0, grpavp_sub1)// 0, fixed to terminate

				CHECK_FCT_DO( fd_msg_avp_add( grpavp, MSG_BRW_LAST_CHILD, grpavp_sub1 ), goto out  );
				
				LOG_D("fj CCA Final-Unit-Indication Ok\n");
			}
			
		}
	
                struct dict_object *rate_group = NULL;
                EN_GRPAVP_U32("Rating-Group", 0, rate_group, gy_ptr->rating_group); //fixed for COOK, should be the same as CCR

                if(gy_ptr->service_identifier >= 0)// huawei has no si in CCR, and should not include si in CCA; iplook has si in CCR, and should include si in CCA.
                {
                    struct dict_object *service_id = NULL;
                    EN_GRPAVP_U32("Service-Identifier", 0, service_id, gy_ptr->service_identifier);
                }

                struct dict_object *valid_time = NULL;
                EN_GRPAVP_U32("Validity-Time", 0, valid_time, valid_time_len);

		if (gy_ptr->request_type != RT_TERMINATE_REQUEST)
		{
		/* Granted-Service-Unit */
		struct dict_object *granted_service_unit = NULL;
		SEARCH_AVP_("Granted-Service-Unit", 0, &granted_service_unit);
		{
			CHECK_FCT_DO( fd_msg_avp_new ( granted_service_unit, 0, &grpavp_sub1 ), goto out  );
			if(gy_port->service_type == ST_PS_DATA)
			{
				EN_GRPAVP_U64_("CC-Total-Octets", 0, cc_total_octects, granted_value, grpavp_sub1)
				/*if (granted_value > 0)
				{
					EN_GRPAVP_U32_("CC-Time", 0, cc_time, 2400, grpavp_sub1)
				}
				else
				{
					EN_GRPAVP_U32_("CC-Time", 0, cc_time, 0, grpavp_sub1)
				}*/
			}
			else
				EN_GRPAVP_U32_("CC-Time", 0, cc_time, granted_value, grpavp_sub1)

			CHECK_FCT_DO( fd_msg_avp_add( grpavp, MSG_BRW_LAST_CHILD, grpavp_sub1 ), goto out  );
			
			LOG_D("fj CCA Granted-Service-Unit Ok\n");
		}
		}

		/*if(granted_value > 0)
		{
			struct dict_object *time_threshold = NULL;
			gy_ptr->msg_body.cca.time_threshold = 60;
			EN_GRPAVP_U32("Time-Quota-Threshold", 10415, time_threshold, gy_ptr->msg_body.cca.time_threshold);
		}*/

		if(gy_ptr->request_type != RT_TERMINATE_REQUEST)
		{
			struct dict_object *volume_threshold = NULL;
			EN_GRPAVP_U32("Volume-Quota-Threshold", 10415, volume_threshold, gy_ptr->msg_body.cca.volume_threshold);		

			struct dict_object *quota_hold_time = NULL;
			EN_GRPAVP_U32("Quota-Holding-Time", 10415, quota_hold_time, gy_ptr->msg_body.cca.time_threshold + 10);		

			if(1)
			{
				struct dict_object *time_threshold = NULL;
				EN_GRPAVP_U32("Time-Quota-Threshold", 10415, time_threshold, gy_ptr->msg_body.cca.time_threshold);
			}
			
		}
		
		CHECK_FCT_DO( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, grpavp ), goto out  );
		
		LOG_D("fj CCA Multiple-Services-Credit-Control Ok\n");
	}

	/* Send the answer */
	pAnsPtr = &ans;
	//CHECK_FCT_DO( fd_msg_send((struct msg **)g_ccr_msg_ptr_ptr[gy_ptr->fd_port], NULL, NULL ), goto out );
	//CHECK_FCT_DO( fd_msg_send(pAnsPtr, NULL, NULL ), goto out );
	fd_msg_send(pAnsPtr, NULL, NULL );
	/*pthread_mutex_lock(&gy_cca_lock);
	ret = fd_msg_send(pAnsPtr, NULL, NULL);
	pthread_mutex_unlock(&gy_cca_lock);
	if (ret != 0)
	{
		goto out;
	}*/

	if(gy_ptr->msg_body.cca.is_final)
	{
		gy_release_port(gy_ptr->fd_port);
	}
out:
	return 1;
}

static int gx_send_cca_fail(_gy_msg *gy_ptr)
{
	//struct msg *req = NULL;
	struct msg *ans;//, *qry;
	struct avp *avp = NULL;
	struct avp *grpavp = NULL;
	struct avp *grpavp_sub1 = NULL;
	union avp_value val;
	//struct dict_object *dict_obj_tmp = NULL;
	struct msg **pAnsPtr = NULL;
	//int ret;

	long	granted_value = gy_ptr->msg_body.cca.grant_value;
	long valid_time_len = 3;

	gx_stat_increase_send_cca(gy_ptr->request_type);
	
	//ans = g_ccr_msg_ptr[port];
	ans = g_direct_cca_fail_msg_ptr;

	//memset(ans, 0x00, sizeof(ans));
//	CHECK_FCT_DO( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, &ans, 0 ) , goto out);
	
	/* set application id */
	{
		struct msg_hdr * msg_hdr = NULL;
		ASSERT( 0 == fd_msg_hdr ( ans, &msg_hdr ) );
		msg_hdr->msg_appl = SH_APP_ID;
		msg_hdr->msg_flags = msg_hdr->msg_flags | (CMD_FLAG_PROXIABLE);
	}

	/* Set the Origin-Host, Origin-Realm, Result-Code AVPs */
	EN_AVP_U32(result_code, 4001, ans, "fj CCA Result-Code");// DIAMETER_AUTHENTICATION_REJECTED

	/* Get the auth_app_id and from the reply and set it in the reply */
	EN_AVP_U32(auth_app_id, 4, ans, "fj CCA Auth-Application-ID");
	EN_AVP_U32(cc_req_type, gy_ptr->request_type, ans, "fj CCA cc_req_type");
	EN_AVP_U32(cc_req_num, gy_ptr->request_number, ans, "fj CCA cc_req_num");

	if (gy_ptr->request_type == RT_EVENT_REQUEST)
	{
		if ((gy_ptr->msg_body.ccr.request_action == RA_CHECK_BALANCE)\
			&& (gy_ptr->msg_body.cca.result == 2001))// only support CHECK_BALANCE in event request
		{
			EN_AVP_U32(check_balance_result, gy_ptr->msg_body.cca.check_balance_result, ans, "fj CCA check_balance_result");
		}
	}
	else
	/* Multiple-Services-Credit-Control */
	{
		CHECK_FCT_DO( fd_msg_avp_new ( multiple_services_credit_control, 0, &grpavp ), goto out  );

		/* Result-Code */
		struct dict_object *result_code = NULL;
		if(gy_ptr->msg_body.cca.result < 2001)
			gy_ptr->msg_body.cca.result = 2001;		
		EN_GRPAVP_U32("Result-Code", 0, result_code, gy_ptr->msg_body.cca.result); 

		/*if(gy_ptr->msg_body.cca.is_final && gy_ptr->msg_body.cca.result == 2001) //only successful result can contain this AVP
		{
			struct dict_object *final_unit_indication = NULL;
			SEARCH_AVP_("Final-Unit-Indication", 0, &final_unit_indication);
			{
				CHECK_FCT_DO( fd_msg_avp_new ( final_unit_indication, 0, &grpavp_sub1 ), goto out  );
			
				EN_GRPAVP_U32_("Final-Unit-Action", 0, final_unit_action, 0, grpavp_sub1)// 0, fixed to terminate

				CHECK_FCT_DO( fd_msg_avp_add( grpavp, MSG_BRW_LAST_CHILD, grpavp_sub1 ), goto out  );
				
				LOG_D("fj CCA Final-Unit-Indication Ok\n");
			}
			
		}*/
	
                struct dict_object *rate_group = NULL;
                EN_GRPAVP_U32("Rating-Group", 0, rate_group, gy_ptr->rating_group); //fixed for COOK, should be the same as CCR

                if(gy_ptr->service_identifier >= 0)// huawei has no si in CCR, and should not include si in CCA; iplook has si in CCR, and should include si in CCA.
                {
                    struct dict_object *service_id = NULL;
                    EN_GRPAVP_U32("Service-Identifier", 0, service_id, gy_ptr->service_identifier);
                }

                struct dict_object *valid_time = NULL;
                EN_GRPAVP_U32("Validity-Time", 0, valid_time, valid_time_len);

	
		/* Granted-Service-Unit */
		struct dict_object *granted_service_unit = NULL;
		SEARCH_AVP_("Granted-Service-Unit", 0, &granted_service_unit);
		{
			CHECK_FCT_DO( fd_msg_avp_new ( granted_service_unit, 0, &grpavp_sub1 ), goto out  );
			if(gy_ptr->service_type == ST_PS_DATA)
			{
				EN_GRPAVP_U64_("CC-Total-Octets", 0, cc_total_octects, granted_value, grpavp_sub1)
				/*if (granted_value > 0)
				{
					EN_GRPAVP_U32_("CC-Time", 0, cc_time, 2400, grpavp_sub1)
				}
				else
				{
					EN_GRPAVP_U32_("CC-Time", 0, cc_time, 0, grpavp_sub1)
				}*/
			}
			else
				EN_GRPAVP_U32_("CC-Time", 0, cc_time, granted_value, grpavp_sub1)

			CHECK_FCT_DO( fd_msg_avp_add( grpavp, MSG_BRW_LAST_CHILD, grpavp_sub1 ), goto out  );
			
			LOG_D("fj CCA Granted-Service-Unit Ok\n");
		}

		/*if(granted_value > 0)
		{
			struct dict_object *time_threshold = NULL;
			gy_ptr->msg_body.cca.time_threshold = 60;
			EN_GRPAVP_U32("Time-Quota-Threshold", 10415, time_threshold, gy_ptr->msg_body.cca.time_threshold);
		}*/

		/*if(gy_ptr->request_type != RT_TERMINATE_REQUEST)
		{
			struct dict_object *volume_threshold = NULL;
			EN_GRPAVP_U32("Volume-Quota-Threshold", 10415, volume_threshold, gy_ptr->msg_body.cca.volume_threshold);		

			struct dict_object *quota_hold_time = NULL;
			EN_GRPAVP_U32("Quota-Holding-Time", 10415, quota_hold_time, 750);		
		}*/
		
		CHECK_FCT_DO( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, grpavp ), goto out  );
		
		LOG_D("fj CCA Multiple-Services-Credit-Control Ok\n");
	}

	/* Send the answer */
	pAnsPtr = &ans;
	//CHECK_FCT_DO( fd_msg_send((struct msg **)g_ccr_msg_ptr_ptr[gy_ptr->fd_port], NULL, NULL ), goto out );
	//CHECK_FCT_DO( fd_msg_send(pAnsPtr, NULL, NULL ), goto out );
	fd_msg_send(pAnsPtr, NULL, NULL );
	/*pthread_mutex_lock(&gy_cca_lock);
	ret = fd_msg_send(pAnsPtr, NULL, NULL);
	pthread_mutex_unlock(&gy_cca_lock);
	if (ret != 0)
	{
		goto out;
	}*/

	/*if(gy_ptr->msg_body.cca.is_final)
	{
		gy_release_port(gy_ptr->fd_port);
	}*/
out:
	return 1;
}

int gx_send_ccr_real(struct gx_sm_t **sm , struct dict_object *cmd_r, _gy_msg *msg_ptr) 
{
	struct msg *req = NULL;
	struct avp *avp = NULL;
	struct avp *grpavp = NULL;
	struct avp *grpavp_sub1 = NULL;
	struct avp *grpavp_sub2 = NULL;
	struct avp *grpavp_sub3 = NULL;
#if	PS_ENABLED
	struct avp *grpavp_sub4 = NULL;
#endif
	union avp_value val;
	struct session *sess = NULL;
	struct gx_sm_t *gx_sm = NULL;
	struct dict_object *dict_obj_tmp = NULL;
	char	tmp_buf[128], value_buf[128];
	struct in_addr	  hostAddr;
	hostAddr.s_addr = GetLocalIP();
	char* phostAddr = inet_ntoa(hostAddr);

	int	port = msg_ptr->fd_port;
	//int	cxt_port;
	_gy_port 	*gy_port = NULL;
	int  tmp_len =0, len;
	
	gy_port = gy_get_port_space(port);
	if(gy_port == NULL)
		return 0;

	gy_port->updated_ts = ts_sec;
	gy_port->app_port = msg_ptr->app_port;
	//cxt_port = gy_port->cxt_port;
	
	LOG_N("fj gx_send_ccr_real enter");

	gx_stat_increase_send_ccr(msg_ptr->request_type);
	
	/* Create the request from template */
	CHECK_FCT_DO( fd_msg_new( cmd_r, MSGFL_ALLOC_ETEID, &req ), goto out1 );

	/* set application id */
	{
		struct msg_hdr * msg_hdr = NULL;
		ASSERT( 0 == fd_msg_hdr ( req, &msg_hdr ) );
		msg_hdr->msg_flags = msg_hdr->msg_flags & (~CMD_FLAG_PROXIABLE);
	}

	gx_sm = *sm;
	/* Create a new session */
 //   if(!gx_sm->sess)
	if(gy_sess[gy_port->index] == NULL)
	{
		CHECK_FCT_DO( fd_sess_new( &sess, 
			fd_g_config->cnf_diamid, 
			fd_g_config->cnf_diamid_len, 
			(uint8_t *)("CCR_SESSION"), 
			strlen("CCR_SESSION") ), goto out );

		gy_sess[gy_port->index] = sess;
		//Hold the session till terminate happens
		CHECK_FCT( fd_sess_ref_msg(sess) );
    }
	else
	{
		//sess = gx_sm->sess;
		sess = gy_sess[gy_port->index];
		printf("use previous session %p \n", sess);
    }

	// fd_sess_dump( 0 , sess);

	// dump_sess_eyec( sess, __FUNCTION__);
	/* Now set all AVPs values */

	/* Session-Id */
	{
		os0_t sid;
		size_t sidlen;
		struct dict_object *sess_id = NULL;
		CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &sess_id, ENOENT) );

		CHECK_FCT_DO( fd_sess_getsid ( sess, &sid, &sidlen ), goto out );
		CHECK_FCT_DO( fd_msg_avp_new ( sess_id, 0, &avp ), goto out );
		val.os.data = sid;
		val.os.len  = sidlen;
		
		fd_get_session_id((char *)val.os.data, tmp_buf, 0);
		fd_update_cxt_id(port, tmp_buf);
		
		printf("\r\ncxt_port=%d, app_port=%d, session id=%s\r\n", port, gy_port->app_port, tmp_buf); 
		
		CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out );
		CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_FIRST_CHILD, avp ), goto out );
	}

    char *pRealm = g_sh_conf_ext.pi_diamid_realm_peer, *pHost = g_sh_conf_ext.pi_diamid_peer;
    if ((msg_ptr->service_type == ST_CS_SMS) || (msg_ptr->service_type == ST_CS_VOICE))
    {
        GetRoDiamIdPeer(&pRealm, &pHost, (msg_ptr->service_type == ST_CS_SMS)?1:0);
    }
    if (pRealm == NULL || pHost == NULL)
    {
        LOG_N("fj gx_send_ccr_real, no link available, pRealm[%p], pHost[%p]", pRealm, pHost);
        return 0;
    }
    /*if ((msg_ptr->service_type == ST_CS_SMS) && (g_rosms_conf_ext.pi_diamid_realm_peer!=NULL) && (g_rosms_conf_ext.pi_diamid_peer!=NULL))
    {
        pRealm = g_rosms_conf_ext.pi_diamid_realm_peer;
        pHost = g_rosms_conf_ext.pi_diamid_peer;
    }
    else if ((msg_ptr->service_type == ST_CS_VOICE) && (g_rovoice_conf_ext.pi_diamid_realm_peer!=NULL) && (g_rovoice_conf_ext.pi_diamid_peer!=NULL))
    {
        pRealm = g_rovoice_conf_ext.pi_diamid_realm_peer;
        pHost = g_rovoice_conf_ext.pi_diamid_peer;
    }*/

	/* Destination-Realm */
	EN_AVP_STR(dest_realm, pRealm, req, "fj CCR Destination-Realm Ok");

	/* Destination-Host */
	EN_AVP_STR(dest_host, pHost, req, "fj CCR Destination-Host-Ok");
	
	/* Origin-Host & Origin-Realm */
	CHECK_FCT_DO( fd_msg_add_origin ( req, 0 ), goto out  );

	/* Auth-Application-Id */
	EN_AVP_U32(auth_app_id, 4, req, "fj CCR Auth-Application-ID");

	/* Service-Context-ID */
	if(msg_ptr->service_type == ST_CS_SMS)
	{
		//EN_AVP_STR(service_cxt_id, "agrandtech_sms@3gpp.org", req, "fj CCR Service-Context-ID Ok");
		EN_AVP_STR(service_cxt_id, fd_g_config->service_context_sms, req, "fj CCR Service-Context-ID Ok");
		//EN_AVP_STR(route_record,  "ocsclient.seagullCTF.org", req , "fj CCR Route-Record OK");
	}
	else
	{
		//EN_AVP_STR(service_cxt_id, "agrandtech_ro@3gpp.org", req, "fj CCR Service-Context-ID Ok");
		EN_AVP_STR(service_cxt_id, fd_g_config->service_context_voice, req, "fj CCR Service-Context-ID Ok");
	}
	
    /* CC-Request-Type */
    {
#define CCR_INIT_REQUEST		1
#define CCR_UPDATE_REQUEST		2
#define CCR_TERMINATION_REQUEST 	3
#define CCR_EVENT_REQUEST		4
		//TODO Change this to use  enum object
		CHECK_FCT_DO( fd_msg_avp_new ( cc_req_type, 0, &avp ), goto out  );
		/*
		if(gx_sm->state == STATE_INIT)
			val.i32 = CCR_INIT_REQUEST;
		else if(gx_sm->state == STATE_FINAL)
			val.i32 = CCR_TERMINATION_REQUEST;
		else 
			val.i32 = CCR_UPDATE_REQUEST;
		*/
		if(msg_ptr->request_type>RT_EVENT_REQUEST)
			val.i32 = RT_EVENT_REQUEST;
		else
			val.i32 = msg_ptr->request_type;
		
		CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
		CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
    }

	/* CC-Requested-Action */
	if(msg_ptr->service_type == ST_CS_SMS)
		EN_AVP_U32(requested_action, msg_ptr->msg_body.ccr.request_action, req, "fj CCR Requested-Action");

    /* CC-Request-Number */
	EN_AVP_U32(cc_req_num, msg_ptr->request_number, req, "fj CCR CC-Request-Number");

	/* Event-Timestamp */

	time_t_to_diameter_timestamp(tmp_buf);
	EN_AVP_BCDSTR(event_timestamp, tmp_buf, 4, req, "fj CCR Event-Timestamp");
	
	/* Subscription-Id */
	{
		int offset = 0;
		if(msg_ptr->msg_body.ccr.role_of_node == 0)
		{
			if(msg_ptr->msg_body.ccr.caller[0] == '+')
				offset = 1;
			sprintf(tmp_buf, "%s", &msg_ptr->msg_body.ccr.caller[offset]);
		}
		else	 if(msg_ptr->msg_body.ccr.role_of_node == 1)
		{
			if(msg_ptr->msg_body.ccr.called[0] == '+')
				offset = 1;

			sprintf(tmp_buf, "%s", &msg_ptr->msg_body.ccr.called[offset]);
		}
		else	 if(msg_ptr->msg_body.ccr.role_of_node == 2)
		{
			if(msg_ptr->msg_body.ccr.caller[0] == '+')
				offset = 1;

			sprintf(tmp_buf, "%s", &msg_ptr->msg_body.ccr.caller[offset]);
		}
		
		CHECK_FCT_DO( fd_msg_avp_new ( subscription_id, 0, &grpavp ), goto out  );

		EN_GRPAVP_U32_("Subscription-Id-Type", 0, subscription_id_type, 0, grpavp);
		EN_GRPAVP_STR("Subscription-Id-Data", 0, subscription_id_data, tmp_buf, grpavp);

		CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, grpavp ), goto out  );

		if(1)
		{
			tmp_len = strlen(msg_ptr->msg_body.ccr.imsi);
			if(tmp_len>4)
			{
				strcpy(tmp_buf, msg_ptr->msg_body.ccr.imsi); 
				CHECK_FCT_DO( fd_msg_avp_new ( subscription_id, 0, &grpavp ), goto out  );

				EN_GRPAVP_U32_("Subscription-Id-Type", 0, subscription_id_type, 1, grpavp);
				EN_GRPAVP_STR("Subscription-Id-Data", 0, subscription_id_data, tmp_buf, grpavp);

				CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, grpavp ), goto out  );				
			}			
		}
			
	}

	/* Service-Information */
	{
		CHECK_FCT_DO( fd_msg_avp_new ( service_information, 0, &grpavp ), goto out  );

		/* AoC-Information */
		/* SMS-Information */

		if(msg_ptr->service_type == ST_CS_SMS)
		{

			struct dict_object *SMS_Information = NULL;
			SEARCH_AVP_("SMS-Information", SH_VND_ID, &SMS_Information);
			CHECK_FCT_DO( fd_msg_avp_new ( SMS_Information, 0, &grpavp_sub1 ), goto out);
		
			EN_GRPAVP_U32_("SMS-Node", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub1)
			/*
			EN_GRPAVP_U32_("SM-Message-Type", SH_VND_ID, dict_obj_tmp, 0, grpavp_sub1)					
			*/
			EN_GRPAVP_U32_("Number-Of-Messages-Sent", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub1)
			/*
			EN_GRPAVP_U32_("SM-Service-Type", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub1)
			*/
			EN_GRPAVP_STR("SMSC-Address", SH_VND_ID, dict_obj_tmp, msg_ptr->msg_body.ccr.smsc, grpavp_sub1)
			
			/*
			struct dict_object *SMSC_Address = NULL;
			SEARCH_AVP_("SMSC-Address", SH_VND_ID, &SMSC_Address);
			CHECK_FCT_DO( fd_msg_avp_new ( SMSC_Address, 0, &grpavp_sub2 ), goto out);
			{
				EN_GRPAVP_U32_("Address-Type", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub2)
				EN_GRPAVP_STR("Address-Data", SH_VND_ID, dict_obj_tmp, msg_ptr->msg_body.ccr.smsc, grpavp_sub2)

				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}
			*/
			struct dict_object *Originator_Received_Address = NULL;
			SEARCH_AVP_("Originator-Received-Address", SH_VND_ID, &Originator_Received_Address);
			CHECK_FCT_DO( fd_msg_avp_new ( Originator_Received_Address, 0, &grpavp_sub2 ), goto out);
			{
				EN_GRPAVP_U32_("Address-Type", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub2)
				EN_GRPAVP_STR("Address-Data", SH_VND_ID, dict_obj_tmp, msg_ptr->msg_body.ccr.caller, grpavp_sub2)

				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}

			struct dict_object *Recipient_Info = NULL;
			SEARCH_AVP_("Recipient-Info", SH_VND_ID, &Recipient_Info);
			CHECK_FCT_DO( fd_msg_avp_new ( Recipient_Info, 0, &grpavp_sub2 ), goto out);
			{
				struct dict_object *Recipient_Address = NULL;
				SEARCH_AVP_("Recipient-Address", SH_VND_ID, &Recipient_Address);
				CHECK_FCT_DO( fd_msg_avp_new ( Recipient_Address, 0, &grpavp_sub3 ), goto out);
				{
					EN_GRPAVP_U32_("Address-Type", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub3)
					EN_GRPAVP_STR("Address-Data", SH_VND_ID, dict_obj_tmp, msg_ptr->msg_body.ccr.called, grpavp_sub3)
							
					CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub2, MSG_BRW_LAST_CHILD, grpavp_sub3 ), goto out  );
				}

				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}	

			if(msg_ptr->msg_body.ccr.cellid_presented == 1)
			{
			
				/* fj added 2021.2.24 for OCS CCR witch avp Service-Specific-Info */			
				struct dict_object *service_specific_info = NULL;			
				SEARCH_AVP_("Service-Specific-Info", SH_VND_ID, &service_specific_info);			
				CHECK_FCT_DO( fd_msg_avp_new ( service_specific_info, 0, &grpavp_sub2 ), goto out);			
				{				/* ¸ù¾ÝÐèÒªÓ¦ÓÃ²ãÌîÈë²ÎÊý */				
					EN_GRPAVP_U32_("Service-Specific-Type", SH_VND_ID, dict_obj_tmp, 6006, grpavp_sub2)				
					EN_GRPAVP_STR("Service-Specific-Data", SH_VND_ID, dict_obj_tmp, msg_ptr->msg_body.ccr.cellid, grpavp_sub2)				
					CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );			
				}
			}

		      CHECK_FCT_DO( fd_msg_avp_add( grpavp, MSG_BRW_LAST_CHILD, grpavp_sub1 ), goto out  );
			
		}	
		else  		/* IMS-Information */
		{
			CHECK_FCT_DO( fd_msg_avp_new ( ims_information, 0, &grpavp_sub1 ), goto out  );
		
			EN_GRPAVP_U32_("Node-Functionality", SH_VND_ID, dict_obj_tmp, 6, grpavp_sub1)


			if(msg_ptr->msg_body.ccr.cellid_presented == 1)
			{
			
				/* fj added 2021.2.24 for OCS CCR witch avp Service-Specific-Info */			
				struct dict_object *service_specific_info = NULL;			
				SEARCH_AVP_("Service-Specific-Info", SH_VND_ID, &service_specific_info);			
				CHECK_FCT_DO( fd_msg_avp_new ( service_specific_info, 0, &grpavp_sub2 ), goto out);			
				{				/* ¸ù¾ÝÐèÒªÓ¦ÓÃ²ãÌîÈë²ÎÊý */				
					EN_GRPAVP_U32_("Service-Specific-Type", SH_VND_ID, dict_obj_tmp, 6006, grpavp_sub2)				
					EN_GRPAVP_STR("Service-Specific-Data", SH_VND_ID, dict_obj_tmp, msg_ptr->msg_body.ccr.cellid, grpavp_sub2)				
					CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );			
				}
			}
			
			struct dict_object *event_type = NULL;
			SEARCH_AVP_("Event-Type", SH_VND_ID, &event_type);
			CHECK_FCT_DO( fd_msg_avp_new ( event_type, 0, &grpavp_sub2 ), goto out);
			{
				EN_GRPAVP_STR("SIP-Method", SH_VND_ID, dict_obj_tmp, "INVITE", grpavp_sub2)
	
				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}

			EN_GRPAVP_U32_("Role-of-Node", SH_VND_ID, dict_obj_tmp, msg_ptr->msg_body.ccr.role_of_node, grpavp_sub1)

			sprintf( tmp_buf,"%04d.agt@%s", msg_ptr->fd_port, phostAddr );			
			EN_GRPAVP_STR("User-Session-Id", SH_VND_ID, dict_obj_tmp, tmp_buf, grpavp_sub1)
		
			/* Time-Stamps */
			CHECK_FCT_DO( fd_msg_avp_new ( time_stamps, 0, &grpavp_sub2 ), goto out);
			{
				EN_GRPAVP_STR("SIP-Request-Timestamp", SH_VND_ID, dict_obj_tmp, "3580", grpavp_sub2)
				EN_GRPAVP_STR("SIP-Response-Timestamp", SH_VND_ID, dict_obj_tmp, "3580", grpavp_sub2)
						
				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}

			/* Inter-Operator-Identifier */
			struct dict_object *inter_operator_identifier = NULL;
			SEARCH_AVP_("Inter-Operator-Identifier", SH_VND_ID, &inter_operator_identifier);
			CHECK_FCT_DO( fd_msg_avp_new ( inter_operator_identifier, 0, &grpavp_sub2 ), goto out);
			{
				EN_GRPAVP_STR("Originating-IOI", SH_VND_ID, dict_obj_tmp, fd_g_config->cnf_diamid, grpavp_sub2)
				
//				EN_GRPAVP_STR("Originating-IOI", SH_VND_ID, dict_obj_tmp, "agrandtech_ocs@3gpp.org", grpavp_sub2)
				EN_GRPAVP_STR("Terminating-IOI", SH_VND_ID, dict_obj_tmp, pHost, grpavp_sub2)
						
				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}

			EN_GRPAVP_STR("IMS-Charging-Identifier", SH_VND_ID, dict_obj_tmp, "286eae5698fb00530e05090ffee03c60.3580811571.1100844.12", grpavp_sub1)

			if(msg_ptr->service_type != ST_CS_SMS)
			{
		
				sprintf(tmp_buf, "v=0 o=- 26967515390 IN IP4 %s s=SBC call c=IN IP4 %s t=0 0", phostAddr, phostAddr);	
				EN_GRPAVP_STR("SDP-Session-Description", SH_VND_ID, dict_obj_tmp, tmp_buf, grpavp_sub1)

				/* SDP-Media-Component */
				struct dict_object *sdp_media_component = NULL;
				SEARCH_AVP_("SDP-Media-Component", SH_VND_ID, &sdp_media_component);
				CHECK_FCT_DO( fd_msg_avp_new ( sdp_media_component, 0, &grpavp_sub2 ), goto out);
				{
					EN_GRPAVP_STR("SDP-Media-Name", SH_VND_ID, dict_obj_tmp, "audio 19556 RTP/AVP 8 101", grpavp_sub2)
					EN_GRPAVP_STR("SDP-Media-Description", SH_VND_ID, dict_obj_tmp, " a=rtpmap:8 PCMA/8000 a=rtpmap:101 telephone-event/8000 a=fmtp:101 0-15 a=ptime:20 a=sendrecv", grpavp_sub2)
							
					CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
				}

				/* Message-Body */
				struct dict_object *message_body = NULL;
				SEARCH_AVP_("Message-Body", SH_VND_ID, &message_body);
				CHECK_FCT_DO( fd_msg_avp_new ( message_body, 0, &grpavp_sub2 ), goto out);
				{
					EN_GRPAVP_STR("Content-Type", SH_VND_ID, dict_obj_tmp, "application/sdp", grpavp_sub2)
					EN_GRPAVP_U32_("Content-Length", SH_VND_ID, dict_obj_tmp, 22, grpavp_sub2)
							
					CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
					
					LOG_D("fj CCR Message-Body Ok\n");
				}
			}
			
			if(msg_ptr->msg_body.ccr.cellid_presented == 1)
			{
				if (msg_ptr->msg_body.ccr.cellid[3] == 'F')
				{
					char mcc[8]="";
					strncpy(mcc, msg_ptr->msg_body.ccr.cellid, 3);
					sprintf(tmp_buf, "3GPP-GERAN;cgi-3gpp=%s%s", mcc, &msg_ptr->msg_body.ccr.cellid[4]);
				}
				else
				{
					sprintf(tmp_buf, "3GPP-GERAN;cgi-3gpp=%s", msg_ptr->msg_body.ccr.cellid);
				}
			}
            else
            {
			sprintf(tmp_buf, "XDSL;'location-info=%s'", phostAddr );
            }
			EN_GRPAVP_STR("Access-Network-Information", SH_VND_ID, dict_obj_tmp, tmp_buf, grpavp_sub1)

			if(msg_ptr->msg_body.ccr.role_of_node == 2)
				sprintf(tmp_buf, "%s", msg_ptr->msg_body.ccr.origin_caller);
			else	
				sprintf(tmp_buf, "%s", msg_ptr->msg_body.ccr.caller);

		//	sprintf(tmp_buf, "%s", msg_ptr->msg_body.ccr.caller);
			EN_GRPAVP_STR("Calling-Party-Address", SH_VND_ID, dict_obj_tmp, tmp_buf, grpavp_sub1)

			sprintf(tmp_buf, "%s", msg_ptr->msg_body.ccr.called);				
			EN_GRPAVP_STR("Called-Party-Address", SH_VND_ID, dict_obj_tmp, tmp_buf, grpavp_sub1)
			/*
			if(msg_ptr->msg_body.ccr.role_of_node == 0)
			{
				sprintf(tmp_buf, "%s", msg_ptr->msg_body.ccr.caller);
			}
			else
			{
				sprintf(tmp_buf, "%s", msg_ptr->msg_body.ccr.called);				
			}
			EN_GRPAVP_STR("Requested-Party-Address", SH_VND_ID, dict_obj_tmp, tmp_buf, grpavp_sub1)
			*/
			CHECK_FCT_DO( fd_msg_avp_add( grpavp, MSG_BRW_LAST_CHILD, grpavp_sub1 ), goto out  );

		}		

#if	PS_ENABLED
		/* PS-Information */
		struct dict_object *ps_information = NULL;
		SEARCH_AVP_("PS-Information", SH_VND_ID, &ps_information);
		{
			CHECK_FCT_DO( fd_msg_avp_new ( ps_information, 0, &grpavp_sub1 ), goto out  );
	
			EN_GRPAVP_U32_("3GPP-Charging-Id", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub1);
			EN_GRPAVP_U32_("PDN-Connection-ID", SH_VND_ID, dict_obj_tmp, 2, grpavp_sub1);
			EN_GRPAVP_STR("Node-Id", SH_VND_ID, dict_obj_tmp, "Node-Id", grpavp_sub1);
			EN_GRPAVP_U32_("3GPP-PDP-Type", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub1);
			EN_GRPAVP_STR("PDP-Address", SH_VND_ID, dict_obj_tmp, "10.10.10.10", grpavp_sub1);
			EN_GRPAVP_U32_("Dynamic-Address-Flag", SH_VND_ID, dict_obj_tmp, 4, grpavp_sub1);
			/* QoS-Information */
			struct dict_object *qos_information = NULL;
			SEARCH_AVP_("QoS-Information", SH_VND_ID, &qos_information);
			CHECK_FCT_DO( fd_msg_avp_new ( qos_information, 0, &grpavp_sub2 ), goto out);
			{
				EN_GRPAVP_U32_("QoS-Class-Identifier", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub2)
				EN_GRPAVP_U32_("Max-Requested-Bandwidth-UL", SH_VND_ID, dict_obj_tmp, 2, grpavp_sub2)
				EN_GRPAVP_U32_("Guaranteed-Bitrate-UL", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub2)
				EN_GRPAVP_U32_("Guaranteed-Bitrate-DL", SH_VND_ID, dict_obj_tmp, 4, grpavp_sub2)
				EN_GRPAVP_STR("Bearer-Identifier", SH_VND_ID, dict_obj_tmp, "Bearer-Identifier", grpavp_sub2)

				/* Allocation-Retention-Priority */
				struct dict_object *allocation_retention_priority = NULL;
				SEARCH_AVP_("Allocation-Retention-Priority", SH_VND_ID, &allocation_retention_priority);
				CHECK_FCT_DO( fd_msg_avp_new ( allocation_retention_priority, 0, &grpavp_sub3 ), goto out);
				{
					EN_GRPAVP_U32_("Priority-Level", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub3)
					EN_GRPAVP_U32_("Pre-emption-Capability", SH_VND_ID, dict_obj_tmp, 2, grpavp_sub3)
					EN_GRPAVP_U32_("Pre-emption-Vulnerability", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub3)
					
					CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub2, MSG_BRW_LAST_CHILD, grpavp_sub3 ), goto out  );
				}
				
				EN_GRPAVP_U32_("APN-Aggregate-Max-Bitrate-UL", SH_VND_ID, dict_obj_tmp, 5, grpavp_sub2)
				EN_GRPAVP_U32_("APN-Aggregate-Max-Bitrate-DL", SH_VND_ID, dict_obj_tmp, 6, grpavp_sub2)

				/* Conditional-APN-Aggregate-Max-Bitrate */
				struct dict_object *conditional_apn_aggregate_max_btrate = NULL;
				SEARCH_AVP_("Conditional-APN-Aggregate-Max-Bitrate", SH_VND_ID, &conditional_apn_aggregate_max_btrate);
				CHECK_FCT_DO( fd_msg_avp_new ( conditional_apn_aggregate_max_btrate, 0, &grpavp_sub3 ), goto out);
				{
					EN_GRPAVP_U32_("APN-Aggregate-Max-Bitrate-UL", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub3)
					EN_GRPAVP_U32_("APN-Aggregate-Max-Bitrate-DL", SH_VND_ID, dict_obj_tmp, 2, grpavp_sub3)
					EN_GRPAVP_U32_("IP-CAN-Type", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub3)
					EN_GRPAVP_U32_("RAT-Type", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub3)
					
					CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub2, MSG_BRW_LAST_CHILD, grpavp_sub3 ), goto out  );
				}

				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}

			EN_GRPAVP_STR("SGSN-Address", SH_VND_ID, dict_obj_tmp, "10.10.10.10", grpavp_sub1);
			EN_GRPAVP_STR("GGSN-Address", SH_VND_ID, dict_obj_tmp, "10.10.10.10", grpavp_sub1);
			EN_GRPAVP_STR("SGW-Address", SH_VND_ID, dict_obj_tmp, "10.10.10.10", grpavp_sub1);
			EN_GRPAVP_STR("CG-Address", SH_VND_ID, dict_obj_tmp, "10.10.10.10", grpavp_sub1);
			EN_GRPAVP_U32_("Serving-Node-Type", SH_VND_ID, dict_obj_tmp, 4, grpavp_sub1);
			EN_GRPAVP_U32_("SGW-Change", SH_VND_ID, dict_obj_tmp, 4, grpavp_sub1);
			EN_GRPAVP_STR("3GPP-IMSI-MCC-MNC", SH_VND_ID, dict_obj_tmp, "3GPP-IMSI-MCC-MNC", grpavp_sub1);
			EN_GRPAVP_U32_("IMSI-Unauthenticated-Flag", SH_VND_ID, dict_obj_tmp, 4, grpavp_sub1);
			EN_GRPAVP_STR("3GPP-GGSN-MCC-MNC", SH_VND_ID, dict_obj_tmp, "3GPP-GGSN-MCC-MNC", grpavp_sub1);
			EN_GRPAVP_STR("3GPP-NSAPI", SH_VND_ID, dict_obj_tmp, "3GPP-NSAPI", grpavp_sub1);
			EN_GRPAVP_STR("Called-Station-Id", 0, dict_obj_tmp, "Called-Station-Id", grpavp_sub1);
			EN_GRPAVP_STR("3GPP-Session-Stop-Indicator", SH_VND_ID, dict_obj_tmp, "3GPP-Session-Stop-Indicator", grpavp_sub1);
			EN_GRPAVP_STR("3GPP-Selection-Mode", SH_VND_ID, dict_obj_tmp, "3GPP-Selection-Mode", grpavp_sub1);
			EN_GRPAVP_STR("3GPP-Charging-Characteristics", SH_VND_ID, dict_obj_tmp, "3GPP-Charging-Characteristics", grpavp_sub1);
			EN_GRPAVP_U32_("Charging-Characteristics-Selection-Mode", SH_VND_ID, dict_obj_tmp, 5, grpavp_sub1);
			EN_GRPAVP_STR("3GPP-SGSN-MCC-MNC", SH_VND_ID, dict_obj_tmp, "3GPP-SGSN-MCC-MNC", grpavp_sub1);
			EN_GRPAVP_STR("3GPP-MS-TimeZone", SH_VND_ID, dict_obj_tmp, "3GPP-MS-TimeZone", grpavp_sub1);
			EN_GRPAVP_STR("Charging-Rule-Base-Name", SH_VND_ID, dict_obj_tmp, "Charging-Rule-Base-Name", grpavp_sub1);
			EN_GRPAVP_STR("3GPP-User-Location-Info", SH_VND_ID, dict_obj_tmp, "3GPP-User-Location-Info", grpavp_sub1);

			/* User-CSG-Information */
			struct dict_object *user_csg_information = NULL;
			SEARCH_AVP_("User-CSG-Information", SH_VND_ID, &user_csg_information);
			CHECK_FCT_DO( fd_msg_avp_new ( user_csg_information, 0, &grpavp_sub2 ), goto out);
			{
				EN_GRPAVP_U32_("CSG-Id", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub2)
				EN_GRPAVP_U32_("CSG-Access-Mode", SH_VND_ID, dict_obj_tmp, 2, grpavp_sub2)
				EN_GRPAVP_U32_("CSG-Membership-Indication", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub2)
				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}

			EN_GRPAVP_STR("3GPP2-BSID", 5535, dict_obj_tmp, "3GPP2-BSID", grpavp_sub1);
			EN_GRPAVP_STR("3GPP-RAT-Type", SH_VND_ID, dict_obj_tmp, "3GPP-RAT-Type", grpavp_sub1);

			/* PS-Furnish-Charging-Information */
			struct dict_object *ps_furnish_charging_information = NULL;
			SEARCH_AVP_("PS-Furnish-Charging-Information", SH_VND_ID, &ps_furnish_charging_information);
			CHECK_FCT_DO( fd_msg_avp_new ( ps_furnish_charging_information, 0, &grpavp_sub2 ), goto out);
			{
				EN_GRPAVP_STR("PS-Free-Format-Data", SH_VND_ID, dict_obj_tmp, "PS-Free-Format-Data", grpavp_sub2)
				EN_GRPAVP_U32_("PS-Append-Free-Format-Data", SH_VND_ID, dict_obj_tmp, 22, grpavp_sub2)
						
				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}
			
			EN_GRPAVP_U32_("PDP-Context-Type", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub1);
			LOG_D("fj CCR PDP-Context-Type Ok\n");
	
			/* Offline-Charging */
			struct dict_object *offline_charging = NULL;
			SEARCH_AVP_("Offline-Charging", SH_VND_ID, &offline_charging);
			CHECK_FCT_DO( fd_msg_avp_new ( offline_charging, 0, &grpavp_sub2 ), goto out);
			{
				EN_GRPAVP_U32_("Quota-Consumption-Time", SH_VND_ID, dict_obj_tmp, 22, grpavp_sub2)
					
				/* Time-Quota-Mechanism */
				struct dict_object *time_quota_mechanism = NULL;
				SEARCH_AVP_("Time-Quota-Mechanism", SH_VND_ID, &time_quota_mechanism);
				CHECK_FCT_DO( fd_msg_avp_new ( time_quota_mechanism, 0, &grpavp_sub3 ), goto out);
				{
					EN_GRPAVP_U32_("Time-Quota-Type", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub3)
					EN_GRPAVP_U32_("Base-Time-Interval", SH_VND_ID, dict_obj_tmp, 2, grpavp_sub3)
					
					CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub2, MSG_BRW_LAST_CHILD, grpavp_sub3 ), goto out  );
				}

				EN_GRPAVP_U32_("Envelope-Reporting", SH_VND_ID, dict_obj_tmp, 22, grpavp_sub2)
						
				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}

			/* Traffic-Data-Volumes */
			struct dict_object *traffic_data_volumes = NULL;
			SEARCH_AVP_("Traffic-Data-Volumes", SH_VND_ID, &traffic_data_volumes);
			CHECK_FCT_DO( fd_msg_avp_new ( traffic_data_volumes, 0, &grpavp_sub2 ), goto out	);
			{
				/* QoS-Information */
				struct dict_object *qos_information = NULL;
				SEARCH_AVP_("QoS-Information", SH_VND_ID, &qos_information);
				CHECK_FCT_DO( fd_msg_avp_new ( qos_information, 0, &grpavp_sub3 ), goto out);
				{
					EN_GRPAVP_U32_("QoS-Class-Identifier", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub3)
					EN_GRPAVP_U32_("Max-Requested-Bandwidth-UL", SH_VND_ID, dict_obj_tmp, 2, grpavp_sub3)
					EN_GRPAVP_U32_("Guaranteed-Bitrate-UL", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub3)
					EN_GRPAVP_U32_("Guaranteed-Bitrate-DL", SH_VND_ID, dict_obj_tmp, 4, grpavp_sub3)
					EN_GRPAVP_STR("Bearer-Identifier", SH_VND_ID, dict_obj_tmp, "Bearer-Identifier", grpavp_sub3)
				
					/* Allocation-Retention-Priority */
					struct dict_object *allocation_retention_priority = NULL;
					SEARCH_AVP_("Allocation-Retention-Priority", SH_VND_ID, &allocation_retention_priority);
					CHECK_FCT_DO( fd_msg_avp_new ( allocation_retention_priority, 0, &grpavp_sub4 ), goto out);
					{
						EN_GRPAVP_U32_("Priority-Level", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub4)
						EN_GRPAVP_U32_("Pre-emption-Capability", SH_VND_ID, dict_obj_tmp, 2, grpavp_sub4)
						EN_GRPAVP_U32_("Pre-emption-Vulnerability", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub4)
						
						CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub3, MSG_BRW_LAST_CHILD, grpavp_sub4 ), goto out  );
					}
					
					EN_GRPAVP_U32_("APN-Aggregate-Max-Bitrate-UL", SH_VND_ID, dict_obj_tmp, 5, grpavp_sub3)
					EN_GRPAVP_U32_("APN-Aggregate-Max-Bitrate-DL", SH_VND_ID, dict_obj_tmp, 6, grpavp_sub3)
				
					/* Conditional-APN-Aggregate-Max-Bitrate */
					struct dict_object *conditional_apn_aggregate_max_btrate = NULL;
					SEARCH_AVP_("Conditional-APN-Aggregate-Max-Bitrate", SH_VND_ID, &conditional_apn_aggregate_max_btrate);
					CHECK_FCT_DO( fd_msg_avp_new ( conditional_apn_aggregate_max_btrate, 0, &grpavp_sub4 ), goto out);
					{
						EN_GRPAVP_U32_("APN-Aggregate-Max-Bitrate-UL", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub4)
						EN_GRPAVP_U32_("APN-Aggregate-Max-Bitrate-DL", SH_VND_ID, dict_obj_tmp, 2, grpavp_sub4)
						EN_GRPAVP_U32_("IP-CAN-Type", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub4)
						EN_GRPAVP_U32_("RAT-Type", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub4)
						
						CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub3, MSG_BRW_LAST_CHILD, grpavp_sub4 ), goto out  );
					}
				
					CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub2, MSG_BRW_LAST_CHILD, grpavp_sub3 ), goto out  );
				}

				EN_GRPAVP_U64_("Accounting-Input-Octets", 0, dict_obj_tmp, 1, grpavp_sub2)
				EN_GRPAVP_U64_("Accounting-Input-Packets", 0, dict_obj_tmp, 2, grpavp_sub2)
				EN_GRPAVP_U64_("Accounting-Output-Octets", 0, dict_obj_tmp, 3, grpavp_sub2)
				EN_GRPAVP_U64_("Accounting-Output-Packets", 0, dict_obj_tmp, 4, grpavp_sub2)
				EN_GRPAVP_U32_("Change-Condition", SH_VND_ID, dict_obj_tmp, 5, grpavp_sub2)
				EN_GRPAVP_STR("Change-Time", SH_VND_ID, dict_obj_tmp, "1111", grpavp_sub2)
				EN_GRPAVP_STR("3GPP-User-Location-Info", SH_VND_ID, dict_obj_tmp, "3GPP-User-Location-Info", grpavp_sub2)

				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}

			/* Service-Data-Container */
			
			/* User-Equipment-Info */
			struct dict_object *user_equipment_info = NULL;
			SEARCH_AVP_("User-Equipment-Info", 0, &user_equipment_info);
			CHECK_FCT_DO( fd_msg_avp_new ( user_equipment_info, 0, &grpavp_sub2 ), goto out	);
			{
				EN_GRPAVP_U32_("User-Equipment-Info-Type", 0, dict_obj_tmp, 1, grpavp_sub2)
				EN_GRPAVP_STR("User-Equipment-Info-Value", 0, dict_obj_tmp, "User-Equipment-Info-Value", grpavp_sub2)
	
				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}
	
			/* Terminal-Information */
			
			EN_GRPAVP_STR("Start-Time", SH_VND_ID, dict_obj_tmp, "2016-08-10T19:09:30-05:00", grpavp_sub1);
			EN_GRPAVP_STR("Stop-Time", SH_VND_ID, dict_obj_tmp, "2016-08-10T19:09:30-05:00 ", grpavp_sub1);
			EN_GRPAVP_U32_("Change-Condition", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub1);
			EN_GRPAVP_U32_("Diagnostics", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub1);
	
			CHECK_FCT_DO( fd_msg_avp_add( grpavp, MSG_BRW_LAST_CHILD, grpavp_sub1 ), goto out  );
		}

#endif

		/* fj added 20170218. for ccr.vcs_information */
		/* VCS-Information */
		tmp_len = strlen(msg_ptr->msg_body.ccr.vlr_number);
		if(tmp_len == 0)
			tmp_len = strlen(msg_ptr->msg_body.ccr.msc_addr);			
		if(tmp_len)
		{
			struct dict_object *vcs_information = NULL;
			SEARCH_AVP_("VCS-Information", SH_VND_ID, &vcs_information);
			{
				CHECK_FCT_DO( fd_msg_avp_new ( vcs_information, 0, &grpavp_sub1 ), goto out  );
				//if(strlen(msg_ptr->msg_body.ccr.msc_addr))
				{
					tmp_len = strlen(msg_ptr->msg_body.ccr.msc_addr);
					fdAsciiToBcd((unsigned char *)tmp_buf, &len, msg_ptr->msg_body.ccr.msc_addr, tmp_len);				
					//sprintf(tmp_buf, "%s", msg_ptr->msg_body.ccr.msc_addr);				
					//EN_GRPAVP_STR("MSC-Address", SH_VND_ID, dict_obj_tmp, tmp_buf, grpavp_sub1);
					EN_GRPAVP_STR_BCD("MSC-Address", SH_VND_ID, dict_obj_tmp, tmp_buf, len, grpavp_sub1);
				}

				/* Basic-Service-Code */
				struct dict_object *basic_service_code = NULL;
				SEARCH_AVP_("Basic-Service-Code", SH_VND_ID, &basic_service_code);
				CHECK_FCT_DO( fd_msg_avp_new ( basic_service_code, 0, &grpavp_sub2 ), goto out	);
				{
					sprintf(value_buf, "%d", 0);
					tmp_len = strlen(value_buf);					
					fdAsciiToBcd((unsigned char *)tmp_buf, &len, value_buf, tmp_len);	
					//EN_GRPAVP_STR("Bearer-Service", SH_VND_ID, dict_obj_tmp, tmp_buf, grpavp_sub2);
					EN_GRPAVP_STR_BCD("Bearer-Service", SH_VND_ID, dict_obj_tmp, tmp_buf, len, grpavp_sub2);

					sprintf(value_buf, "%d", msg_ptr->msg_body.ccr.service_key);
					tmp_len = strlen(value_buf);
					fdAsciiToBcd((unsigned char *)tmp_buf, &len, value_buf, tmp_len);	
					//EN_GRPAVP_STR("Teleservice", SH_VND_ID, dict_obj_tmp, tmp_buf, grpavp_sub2);
					EN_GRPAVP_STR_BCD("Teleservice", SH_VND_ID, dict_obj_tmp, tmp_buf, len, grpavp_sub2);
		
					CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
				}

				//if(strlen(msg_ptr->msg_body.ccr.vlr_number))
				{
					tmp_len = strlen(msg_ptr->msg_body.ccr.vlr_number);
					fdAsciiToBcd((unsigned char *)tmp_buf, &len, msg_ptr->msg_body.ccr.vlr_number, tmp_len);				
					//sprintf(tmp_buf, "%s", msg_ptr->msg_body.ccr.vlr_number);				
					//EN_GRPAVP_STR("VLR-Number", SH_VND_ID, dict_obj_tmp, tmp_buf, grpavp_sub1);
					EN_GRPAVP_STR_BCD("VLR-Number", SH_VND_ID, dict_obj_tmp, tmp_buf, len, grpavp_sub1);
				}
			}

			CHECK_FCT_DO( fd_msg_avp_add( grpavp, MSG_BRW_LAST_CHILD, grpavp_sub1 ), goto out  );
		}

		CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, grpavp ), goto out  );
		
		LOG_D("fj CCR Service-Information Ok\n");
	}

	if(msg_ptr->service_type != ST_CS_SMS)
	{
		/* Service-Identifier */
		EN_AVP_U32(service_identifier, 65534, req, "fj CCR Service-Identifier");

	    /* Multiple-Services-Indicator */
		EN_AVP_U32(multiple_services_indicator, 1, req, "fj CCR Multiple-Services-Indicator");

		/* Multiple-Services-Credit-Control */
		{
			CHECK_FCT_DO( fd_msg_avp_new ( multiple_services_credit_control, 0, &grpavp ), goto out);

			/* Requested-Service-Unit */
			if(msg_ptr->request_type != RT_TERMINATE_REQUEST)		
			{
				CHECK_FCT_DO( fd_msg_avp_new ( requested_service_unit, 0, &grpavp_sub1 ), goto out);
			
				EN_GRPAVP_U32_("CC-Time", 0, dict_obj_tmp, 60, grpavp_sub1)

				CHECK_FCT_DO( fd_msg_avp_add( grpavp, MSG_BRW_LAST_CHILD, grpavp_sub1 ), goto out);
			}
			
			/* Used-Service-Unit */

			if(msg_ptr->msg_body.ccr.used_unit>0 || msg_ptr->request_type == RT_TERMINATE_REQUEST)
			{		
				struct dict_object* used_service_unit = NULL;
				SEARCH_AVP_("Used-Service-Unit", 0, &used_service_unit);
				{
					CHECK_FCT_DO( fd_msg_avp_new ( used_service_unit, 0, &grpavp_sub1 ), goto out);
				
					EN_GRPAVP_U32_("CC-Time", 0, dict_obj_tmp, msg_ptr->msg_body.ccr.used_unit, grpavp_sub1)
		
					CHECK_FCT_DO( fd_msg_avp_add( grpavp, MSG_BRW_LAST_CHILD, grpavp_sub1 ), goto out);
				}
			}

			if(msg_ptr->request_type == RT_UPDATE_REQUEST)
				EN_GRPAVP_U32("Reporting-Reason", SH_VND_ID, reporting_reason, 0);

			CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, grpavp ), goto out  );
		}
	}

	/* CC-Correlation-Id */

	/* User-Equipment-Info */
	
	#if 0
    switch(gx_sm->state) {

     case STATE_INIT:

	{
	//Set Bearer-Usage
    //TODO Change this to use  enum object
       CHECK_FCT_DO( fd_msg_avp_new ( bearer_usage, 0, &avp ), goto out  );
	val.i32 = 1;//IMS
	       CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
	} 
       {
	//Set Packet Filter Operation 
	//TODO Change this to use  enum object
       CHECK_FCT_DO( fd_msg_avp_new ( pflt_oper, 0, &avp ), goto out  );
	val.i32 = 1;//ADDITION
	       CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
	 } 
	struct avp *flt_info = NULL; 
	{
	    //Set Packet Filter Information 
	   CHECK_FCT_DO( fd_msg_avp_new ( pflt_info, 0, &flt_info ), goto out  );

   
	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, flt_info ), goto out  );
	} 
	// Set Packet Filter Identity
	{

	 CHECK_FCT_DO( fd_msg_avp_new ( pflt_id, 0, &avp ), goto out  );
	  val.os.data = (unsigned char *)("ID");
		 val.os.len  = strlen("ID");
	  CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
	  if(flt_info) {
		   CHECK_FCT_DO( fd_msg_avp_add( flt_info, MSG_BRW_LAST_CHILD, avp ), goto out  );
	   }else {
		printf("flt_info NULL\n");
	    }

	 }
	
	CHECK_FCT(fd_sess_state_store(g_hdlr, sess, &gx_sm));

	break;
     case STATE_FINAL:
	 {
	//Set Packet Filter Operation 
	//TODO Change this to use  enum object
       CHECK_FCT_DO( fd_msg_avp_new ( term_cause, 0, &avp ), goto out  );
	val.i32 = 1;//Diameter logout
	       CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
	 } 
	break;
     default: 
	printf("State mismatch \n");
    }
	#else
	/* fj added 20160828: this allow send more than once */
	// CHECK_FCT(fd_sess_state_store(g_hdlr, sess, &gx_sm));
	#endif
	fflush(stderr);

	/* Send the request */
	//printf("CCA %p\n",req);
	// Everthing Done Store the state: reply should retreive it 
	CHECK_FCT_DO( fd_msg_send( &req, gx_rec_cca, NULL ), goto out );

out:
	if(req != NULL)
		fd_msg_free(req);
out1:
	return 1;
}

int gx_send_ccr(struct gx_sm_t **sm , struct dict_object *cmd_r ) 
{
	struct msg *req = NULL;
	struct avp *avp = NULL;
	struct avp *grpavp = NULL;
	struct avp *grpavp_sub1 = NULL;
	struct avp *grpavp_sub2 = NULL;
	struct avp *grpavp_sub3 = NULL;
	struct avp *grpavp_sub4 = NULL;
	union avp_value val;
	struct session *sess = NULL;
	struct gx_sm_t *gx_sm = NULL;
	struct dict_object *dict_obj_tmp = NULL;

	fprintf(stderr, "ECHO ccr send from done...\n");

	LOG_N("fj gx_send_ccr enter");

	/* Create the request from template */
	CHECK_FCT_DO( fd_msg_new( cmd_r, MSGFL_ALLOC_ETEID, &req ), goto out );

	/* set application id */
	{
		struct msg_hdr * msg_hdr = NULL;
		ASSERT( 0 == fd_msg_hdr ( req, &msg_hdr ) );
		msg_hdr->msg_flags = msg_hdr->msg_flags | (CMD_FLAG_PROXIABLE);
	}

	gx_sm = *sm;
	/* Create a new session */
    if(!gx_sm->sess)
	{
		CHECK_FCT_DO( fd_sess_new( &sess, fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len, (uint8_t *)("CCR_SESSION"), strlen("CCR_SESSION") ), goto out );

		printf("statemachine: %p %p %p\n", *(&gx_sm), gx_sm , *sm);
		gx_sm->sess = sess;
		printf("new session %p \n", sess);
		//Hold the session till terminate happens
		CHECK_FCT( fd_sess_ref_msg(sess) );
    }
	else
	{
		sess = gx_sm->sess;
		printf("use previous session %p \n", sess);
    }

	// fd_sess_dump( 0 , sess);

	// dump_sess_eyec( sess, __FUNCTION__);
	/* Now set all AVPs values */

	/* Session-Id */
	{
		os0_t sid;
		size_t sidlen;
		struct dict_object *sess_id = NULL;

		CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &sess_id, ENOENT) );

		CHECK_FCT_DO( fd_sess_getsid ( sess, &sid, &sidlen ), goto out );
		CHECK_FCT_DO( fd_msg_avp_new ( sess_id, 0, &avp ), goto out );
		val.os.data = sid;
		val.os.len  = sidlen;
		CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out );
		CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_FIRST_CHILD, avp ), goto out );
	}

	/* Destination-Realm */
	EN_AVP_STR(dest_realm, g_sh_conf_ext.pi_diamid_realm_peer, req, "fj CCR Destination-Realm Ok");

	/* Destination-Host */
	EN_AVP_STR(dest_host, g_sh_conf_ext.pi_diamid_peer, req, "fj CCR Destination-Host-Ok");
	
	/* Origin-Host & Origin-Realm */
	CHECK_FCT_DO( fd_msg_add_origin ( req, 0 ), goto out  );

	/* Auth-Application-Id */
	EN_AVP_U32(auth_app_id, 4, req, "fj CCR Auth-Application-ID");

	/* Service-Context-ID */
	EN_AVP_STR(service_cxt_id, "32260@3gpp.org", req, "fj CCR Service-Context-ID Ok");

    /* CC-Request-Type */
    {
#define CCR_INIT_REQUEST		1
#define CCR_UPDATE_REQUEST		2
#define CCR_TERMINATION_REQUEST 	3
#define CCR_EVENT_REQUEST		4
		//TODO Change this to use  enum object
		CHECK_FCT_DO( fd_msg_avp_new ( cc_req_type, 0, &avp ), goto out  );
		if(gx_sm->state == STATE_INIT)
			val.i32 = CCR_INIT_REQUEST;
		else if(gx_sm->state == STATE_FINAL)
			val.i32 = CCR_TERMINATION_REQUEST;
		else 
			val.i32 = CCR_UPDATE_REQUEST;

		CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
		CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
    }

    /* CC-Request-Number */
	EN_AVP_U32(cc_req_num, gx_sm->req_num, req, "fj CCR CC-Request-Number");
	gx_sm->req_num++;

	/* Event-Timestamp */
	EN_AVP_STR(event_timestamp, "20130721T135252+00", req, "fj CCR Event-Timestamp");
	
	/* Subscription-Id */
	{
		CHECK_FCT_DO( fd_msg_avp_new ( subscription_id, 0, &grpavp ), goto out  );

		EN_GRPAVP_U32_("Subscription-Id-Type", 0, subscription_id_type, 0, grpavp);
		EN_GRPAVP_STR("Subscription-Id-Data", 0, subscription_id_data, "+23412340001", grpavp);

		CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, grpavp ), goto out  );
	}

	/* Service-Information */
	{
		CHECK_FCT_DO( fd_msg_avp_new ( service_information, 0, &grpavp ), goto out  );

		/* AoC-Information */
		
		/* IMS-Information */
		{
			CHECK_FCT_DO( fd_msg_avp_new ( ims_information, 0, &grpavp_sub1 ), goto out  );

			EN_GRPAVP_U32_("Node-Functionality", SH_VND_ID, dict_obj_tmp, 6, grpavp_sub1)

			struct dict_object *event_type = NULL;
			SEARCH_AVP_("Event-Type", SH_VND_ID, &event_type);
			CHECK_FCT_DO( fd_msg_avp_new ( event_type, 0, &grpavp_sub2 ), goto out);
			{
				EN_GRPAVP_STR("SIP-Method", SH_VND_ID, dict_obj_tmp, "INVITE", grpavp_sub2)
	
				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}

			EN_GRPAVP_U32_("Role-of-Node", SH_VND_ID, dict_obj_tmp, 0, grpavp_sub1)
			EN_GRPAVP_STR("User-Session-Id", SH_VND_ID, dict_obj_tmp, "sbccOVeV.003P3wh421n1w0HG3ezL@192.168.200.2", grpavp_sub1)

			/* Time-Stamps */
			CHECK_FCT_DO( fd_msg_avp_new ( time_stamps, 0, &grpavp_sub2 ), goto out);
			{
				EN_GRPAVP_STR("SIP-Request-Timestamp", SH_VND_ID, dict_obj_tmp, "3580", grpavp_sub2)
				EN_GRPAVP_STR("SIP-Response-Timestamp", SH_VND_ID, dict_obj_tmp, "3580", grpavp_sub2)
						
				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}

			/* Inter-Operator-Identifier */
			struct dict_object *inter_operator_identifier = NULL;
			SEARCH_AVP_("Inter-Operator-Identifier", SH_VND_ID, &inter_operator_identifier);
			CHECK_FCT_DO( fd_msg_avp_new ( inter_operator_identifier, 0, &grpavp_sub2 ), goto out);
			{
				EN_GRPAVP_STR("Originating-IOI", SH_VND_ID, dict_obj_tmp, "spectranet.com.ng", grpavp_sub2)
				EN_GRPAVP_STR("Terminating-IOI", SH_VND_ID, dict_obj_tmp, "spectranet.com.ng", grpavp_sub2)
						
				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}

			EN_GRPAVP_STR("IMS-Charging-Identifier", SH_VND_ID, dict_obj_tmp, "286eae5698fb00530e05090ffee03c60.3580811571.1100844.12", grpavp_sub1)
			EN_GRPAVP_STR("SDP-Session-Description", SH_VND_ID, dict_obj_tmp, " v=0 o=- 26967515390 IN IP4 10.10.80.80 s=SBC call c=IN IP4 10.10.80.80 t=0 0", grpavp_sub1)

			/* SDP-Media-Component */
			struct dict_object *sdp_media_component = NULL;
			SEARCH_AVP_("SDP-Media-Component", SH_VND_ID, &sdp_media_component);
			CHECK_FCT_DO( fd_msg_avp_new ( sdp_media_component, 0, &grpavp_sub2 ), goto out);
			{
				EN_GRPAVP_STR("SDP-Media-Name", SH_VND_ID, dict_obj_tmp, "audio 19556 RTP/AVP 8 101", grpavp_sub2)
				EN_GRPAVP_STR("SDP-Media-Description", SH_VND_ID, dict_obj_tmp, " a=rtpmap:8 PCMA/8000 a=rtpmap:101 telephone-event/8000 a=fmtp:101 0-15 a=ptime:20 a=sendrecv", grpavp_sub2)
						
				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}

			/* Message-Body */
			struct dict_object *message_body = NULL;
			SEARCH_AVP_("Message-Body", SH_VND_ID, &message_body);
			CHECK_FCT_DO( fd_msg_avp_new ( message_body, 0, &grpavp_sub2 ), goto out);
			{
				EN_GRPAVP_STR("Content-Type", SH_VND_ID, dict_obj_tmp, "application/sdp", grpavp_sub2)
				EN_GRPAVP_U32_("Content-Length", SH_VND_ID, dict_obj_tmp, 22, grpavp_sub2)
						
				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
				
				LOG_D("fj CCR Message-Body Ok\n");
			}

			EN_GRPAVP_STR("Access-Network-Information", SH_VND_ID, dict_obj_tmp, " XDSL;'location-info=10.10.80.80'", grpavp_sub1)
			EN_GRPAVP_STR("Calling-Party-Address", SH_VND_ID, dict_obj_tmp, " tel:+23412340001", grpavp_sub1)
			EN_GRPAVP_STR("Called-Party-Address", SH_VND_ID, dict_obj_tmp, " tel:+23412340020", grpavp_sub1)
			EN_GRPAVP_STR("Requested-Party-Address", SH_VND_ID, dict_obj_tmp, " tel:012340020", grpavp_sub1)
			EN_GRPAVP_U32_("huawei_avp_20820", 2011, dict_obj_tmp, 0, grpavp_sub1)
			
			CHECK_FCT_DO( fd_msg_avp_add( grpavp, MSG_BRW_LAST_CHILD, grpavp_sub1 ), goto out  );
		}

		/* PS-Information */
		struct dict_object *ps_information = NULL;
		SEARCH_AVP_("PS-Information", SH_VND_ID, &ps_information);
		{
			CHECK_FCT_DO( fd_msg_avp_new ( ps_information, 0, &grpavp_sub1 ), goto out  );
	
			EN_GRPAVP_U32_("3GPP-Charging-Id", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub1);
			EN_GRPAVP_U32_("PDN-Connection-ID", SH_VND_ID, dict_obj_tmp, 2, grpavp_sub1);
			EN_GRPAVP_STR("Node-Id", SH_VND_ID, dict_obj_tmp, "Node-Id", grpavp_sub1);
			EN_GRPAVP_U32_("3GPP-PDP-Type", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub1);
			EN_GRPAVP_STR("PDP-Address", SH_VND_ID, dict_obj_tmp, "10.10.10.10", grpavp_sub1);
			EN_GRPAVP_U32_("Dynamic-Address-Flag", SH_VND_ID, dict_obj_tmp, 4, grpavp_sub1);
			/* QoS-Information */
			struct dict_object *qos_information = NULL;
			SEARCH_AVP_("QoS-Information", SH_VND_ID, &qos_information);
			CHECK_FCT_DO( fd_msg_avp_new ( qos_information, 0, &grpavp_sub2 ), goto out);
			{
				EN_GRPAVP_U32_("QoS-Class-Identifier", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub2)
				EN_GRPAVP_U32_("Max-Requested-Bandwidth-UL", SH_VND_ID, dict_obj_tmp, 2, grpavp_sub2)
				EN_GRPAVP_U32_("Guaranteed-Bitrate-UL", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub2)
				EN_GRPAVP_U32_("Guaranteed-Bitrate-DL", SH_VND_ID, dict_obj_tmp, 4, grpavp_sub2)
				EN_GRPAVP_STR("Bearer-Identifier", SH_VND_ID, dict_obj_tmp, "Bearer-Identifier", grpavp_sub2)

				/* Allocation-Retention-Priority */
				struct dict_object *allocation_retention_priority = NULL;
				SEARCH_AVP_("Allocation-Retention-Priority", SH_VND_ID, &allocation_retention_priority);
				CHECK_FCT_DO( fd_msg_avp_new ( allocation_retention_priority, 0, &grpavp_sub3 ), goto out);
				{
					EN_GRPAVP_U32_("Priority-Level", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub3)
					EN_GRPAVP_U32_("Pre-emption-Capability", SH_VND_ID, dict_obj_tmp, 2, grpavp_sub3)
					EN_GRPAVP_U32_("Pre-emption-Vulnerability", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub3)
					
					CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub2, MSG_BRW_LAST_CHILD, grpavp_sub3 ), goto out  );
				}
				
				EN_GRPAVP_U32_("APN-Aggregate-Max-Bitrate-UL", SH_VND_ID, dict_obj_tmp, 5, grpavp_sub2)
				EN_GRPAVP_U32_("APN-Aggregate-Max-Bitrate-DL", SH_VND_ID, dict_obj_tmp, 6, grpavp_sub2)

				/* Conditional-APN-Aggregate-Max-Bitrate */
				struct dict_object *conditional_apn_aggregate_max_btrate = NULL;
				SEARCH_AVP_("Conditional-APN-Aggregate-Max-Bitrate", SH_VND_ID, &conditional_apn_aggregate_max_btrate);
				CHECK_FCT_DO( fd_msg_avp_new ( conditional_apn_aggregate_max_btrate, 0, &grpavp_sub3 ), goto out);
				{
					EN_GRPAVP_U32_("APN-Aggregate-Max-Bitrate-UL", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub3)
					EN_GRPAVP_U32_("APN-Aggregate-Max-Bitrate-DL", SH_VND_ID, dict_obj_tmp, 2, grpavp_sub3)
					EN_GRPAVP_U32_("IP-CAN-Type", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub3)
					EN_GRPAVP_U32_("RAT-Type", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub3)
					
					CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub2, MSG_BRW_LAST_CHILD, grpavp_sub3 ), goto out  );
				}

				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}

			EN_GRPAVP_STR("SGSN-Address", SH_VND_ID, dict_obj_tmp, "10.10.10.10", grpavp_sub1);
			EN_GRPAVP_STR("GGSN-Address", SH_VND_ID, dict_obj_tmp, "10.10.10.10", grpavp_sub1);
			EN_GRPAVP_STR("SGW-Address", SH_VND_ID, dict_obj_tmp, "10.10.10.10", grpavp_sub1);
			EN_GRPAVP_STR("CG-Address", SH_VND_ID, dict_obj_tmp, "10.10.10.10", grpavp_sub1);
			EN_GRPAVP_U32_("Serving-Node-Type", SH_VND_ID, dict_obj_tmp, 4, grpavp_sub1);
			EN_GRPAVP_U32_("SGW-Change", SH_VND_ID, dict_obj_tmp, 4, grpavp_sub1);
			EN_GRPAVP_STR("3GPP-IMSI-MCC-MNC", SH_VND_ID, dict_obj_tmp, "3GPP-IMSI-MCC-MNC", grpavp_sub1);
			EN_GRPAVP_U32_("IMSI-Unauthenticated-Flag", SH_VND_ID, dict_obj_tmp, 4, grpavp_sub1);
			EN_GRPAVP_STR("3GPP-GGSN-MCC-MNC", SH_VND_ID, dict_obj_tmp, "3GPP-GGSN-MCC-MNC", grpavp_sub1);
			EN_GRPAVP_STR("3GPP-NSAPI", SH_VND_ID, dict_obj_tmp, "3GPP-NSAPI", grpavp_sub1);
			EN_GRPAVP_STR("Called-Station-Id", 0, dict_obj_tmp, "Called-Station-Id", grpavp_sub1);
			EN_GRPAVP_STR("3GPP-Session-Stop-Indicator", SH_VND_ID, dict_obj_tmp, "3GPP-Session-Stop-Indicator", grpavp_sub1);
			EN_GRPAVP_STR("3GPP-Selection-Mode", SH_VND_ID, dict_obj_tmp, "3GPP-Selection-Mode", grpavp_sub1);
			EN_GRPAVP_STR("3GPP-Charging-Characteristics", SH_VND_ID, dict_obj_tmp, "3GPP-Charging-Characteristics", grpavp_sub1);
			EN_GRPAVP_U32_("Charging-Characteristics-Selection-Mode", SH_VND_ID, dict_obj_tmp, 5, grpavp_sub1);
			EN_GRPAVP_STR("3GPP-SGSN-MCC-MNC", SH_VND_ID, dict_obj_tmp, "3GPP-SGSN-MCC-MNC", grpavp_sub1);
			EN_GRPAVP_STR("3GPP-MS-TimeZone", SH_VND_ID, dict_obj_tmp, "3GPP-MS-TimeZone", grpavp_sub1);
			EN_GRPAVP_STR("Charging-Rule-Base-Name", SH_VND_ID, dict_obj_tmp, "Charging-Rule-Base-Name", grpavp_sub1);
			EN_GRPAVP_STR("3GPP-User-Location-Info", SH_VND_ID, dict_obj_tmp, "3GPP-User-Location-Info", grpavp_sub1);

			/* User-CSG-Information */
			struct dict_object *user_csg_information = NULL;
			SEARCH_AVP_("User-CSG-Information", SH_VND_ID, &user_csg_information);
			CHECK_FCT_DO( fd_msg_avp_new ( user_csg_information, 0, &grpavp_sub2 ), goto out);
			{
				EN_GRPAVP_U32_("CSG-Id", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub2)
				EN_GRPAVP_U32_("CSG-Access-Mode", SH_VND_ID, dict_obj_tmp, 2, grpavp_sub2)
				EN_GRPAVP_U32_("CSG-Membership-Indication", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub2)
				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}

			EN_GRPAVP_STR("3GPP2-BSID", 5535, dict_obj_tmp, "3GPP2-BSID", grpavp_sub1);
			EN_GRPAVP_STR("3GPP-RAT-Type", SH_VND_ID, dict_obj_tmp, "3GPP-RAT-Type", grpavp_sub1);

			/* PS-Furnish-Charging-Information */
			struct dict_object *ps_furnish_charging_information = NULL;
			SEARCH_AVP_("PS-Furnish-Charging-Information", SH_VND_ID, &ps_furnish_charging_information);
			CHECK_FCT_DO( fd_msg_avp_new ( ps_furnish_charging_information, 0, &grpavp_sub2 ), goto out);
			{
				EN_GRPAVP_STR("PS-Free-Format-Data", SH_VND_ID, dict_obj_tmp, "PS-Free-Format-Data", grpavp_sub2)
				EN_GRPAVP_U32_("PS-Append-Free-Format-Data", SH_VND_ID, dict_obj_tmp, 22, grpavp_sub2)
						
				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}
			
			EN_GRPAVP_U32_("PDP-Context-Type", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub1);
			LOG_D("fj CCR PDP-Context-Type Ok\n");
	
			/* Offline-Charging */
			struct dict_object *offline_charging = NULL;
			SEARCH_AVP_("Offline-Charging", SH_VND_ID, &offline_charging);
			CHECK_FCT_DO( fd_msg_avp_new ( offline_charging, 0, &grpavp_sub2 ), goto out);
			{
				EN_GRPAVP_U32_("Quota-Consumption-Time", SH_VND_ID, dict_obj_tmp, 22, grpavp_sub2)
					
				/* Time-Quota-Mechanism */
				struct dict_object *time_quota_mechanism = NULL;
				SEARCH_AVP_("Time-Quota-Mechanism", SH_VND_ID, &time_quota_mechanism);
				CHECK_FCT_DO( fd_msg_avp_new ( time_quota_mechanism, 0, &grpavp_sub3 ), goto out);
				{
					EN_GRPAVP_U32_("Time-Quota-Type", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub3)
					EN_GRPAVP_U32_("Base-Time-Interval", SH_VND_ID, dict_obj_tmp, 2, grpavp_sub3)
					
					CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub2, MSG_BRW_LAST_CHILD, grpavp_sub3 ), goto out  );
				}

				EN_GRPAVP_U32_("Envelope-Reporting", SH_VND_ID, dict_obj_tmp, 22, grpavp_sub2)
						
				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}

			/* Traffic-Data-Volumes */
			struct dict_object *traffic_data_volumes = NULL;
			SEARCH_AVP_("Traffic-Data-Volumes", SH_VND_ID, &traffic_data_volumes);
			CHECK_FCT_DO( fd_msg_avp_new ( traffic_data_volumes, 0, &grpavp_sub2 ), goto out	);
			{
				/* QoS-Information */
				struct dict_object *qos_information = NULL;
				SEARCH_AVP_("QoS-Information", SH_VND_ID, &qos_information);
				CHECK_FCT_DO( fd_msg_avp_new ( qos_information, 0, &grpavp_sub3 ), goto out);
				{
					EN_GRPAVP_U32_("QoS-Class-Identifier", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub3)
					EN_GRPAVP_U32_("Max-Requested-Bandwidth-UL", SH_VND_ID, dict_obj_tmp, 2, grpavp_sub3)
					EN_GRPAVP_U32_("Guaranteed-Bitrate-UL", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub3)
					EN_GRPAVP_U32_("Guaranteed-Bitrate-DL", SH_VND_ID, dict_obj_tmp, 4, grpavp_sub3)
					EN_GRPAVP_STR("Bearer-Identifier", SH_VND_ID, dict_obj_tmp, "Bearer-Identifier", grpavp_sub3)
				
					/* Allocation-Retention-Priority */
					struct dict_object *allocation_retention_priority = NULL;
					SEARCH_AVP_("Allocation-Retention-Priority", SH_VND_ID, &allocation_retention_priority);
					CHECK_FCT_DO( fd_msg_avp_new ( allocation_retention_priority, 0, &grpavp_sub4 ), goto out);
					{
						EN_GRPAVP_U32_("Priority-Level", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub4)
						EN_GRPAVP_U32_("Pre-emption-Capability", SH_VND_ID, dict_obj_tmp, 2, grpavp_sub4)
						EN_GRPAVP_U32_("Pre-emption-Vulnerability", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub4)
						
						CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub3, MSG_BRW_LAST_CHILD, grpavp_sub4 ), goto out  );
					}
					
					EN_GRPAVP_U32_("APN-Aggregate-Max-Bitrate-UL", SH_VND_ID, dict_obj_tmp, 5, grpavp_sub3)
					EN_GRPAVP_U32_("APN-Aggregate-Max-Bitrate-DL", SH_VND_ID, dict_obj_tmp, 6, grpavp_sub3)
				
					/* Conditional-APN-Aggregate-Max-Bitrate */
					struct dict_object *conditional_apn_aggregate_max_btrate = NULL;
					SEARCH_AVP_("Conditional-APN-Aggregate-Max-Bitrate", SH_VND_ID, &conditional_apn_aggregate_max_btrate);
					CHECK_FCT_DO( fd_msg_avp_new ( conditional_apn_aggregate_max_btrate, 0, &grpavp_sub4 ), goto out);
					{
						EN_GRPAVP_U32_("APN-Aggregate-Max-Bitrate-UL", SH_VND_ID, dict_obj_tmp, 1, grpavp_sub4)
						EN_GRPAVP_U32_("APN-Aggregate-Max-Bitrate-DL", SH_VND_ID, dict_obj_tmp, 2, grpavp_sub4)
						EN_GRPAVP_U32_("IP-CAN-Type", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub4)
						EN_GRPAVP_U32_("RAT-Type", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub4)
						
						CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub3, MSG_BRW_LAST_CHILD, grpavp_sub4 ), goto out  );
					}
				
					CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub2, MSG_BRW_LAST_CHILD, grpavp_sub3 ), goto out  );
				}

				EN_GRPAVP_U64_("Accounting-Input-Octets", 0, dict_obj_tmp, 1, grpavp_sub2)
				EN_GRPAVP_U64_("Accounting-Input-Packets", 0, dict_obj_tmp, 2, grpavp_sub2)
				EN_GRPAVP_U64_("Accounting-Output-Octets", 0, dict_obj_tmp, 3, grpavp_sub2)
				EN_GRPAVP_U64_("Accounting-Output-Packets", 0, dict_obj_tmp, 4, grpavp_sub2)
				EN_GRPAVP_U32_("Change-Condition", SH_VND_ID, dict_obj_tmp, 5, grpavp_sub2)
				EN_GRPAVP_STR("Change-Time", SH_VND_ID, dict_obj_tmp, "1111", grpavp_sub2)
				EN_GRPAVP_STR("3GPP-User-Location-Info", SH_VND_ID, dict_obj_tmp, "3GPP-User-Location-Info", grpavp_sub2)

				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}

			/* Service-Data-Container */
			
			/* User-Equipment-Info */
			struct dict_object *user_equipment_info = NULL;
			SEARCH_AVP_("User-Equipment-Info", 0, &user_equipment_info);
			CHECK_FCT_DO( fd_msg_avp_new ( user_equipment_info, 0, &grpavp_sub2 ), goto out	);
			{
				EN_GRPAVP_U32_("User-Equipment-Info-Type", 0, dict_obj_tmp, 1, grpavp_sub2)
				EN_GRPAVP_STR("User-Equipment-Info-Value", 0, dict_obj_tmp, "User-Equipment-Info-Value", grpavp_sub2)
	
				CHECK_FCT_DO( fd_msg_avp_add( grpavp_sub1, MSG_BRW_LAST_CHILD, grpavp_sub2 ), goto out  );
			}
	
			/* Terminal-Information */
			
			EN_GRPAVP_STR("Start-Time", SH_VND_ID, dict_obj_tmp, "2016-08-10T19:09:30-05:00", grpavp_sub1);
			EN_GRPAVP_STR("Stop-Time", SH_VND_ID, dict_obj_tmp, "2016-08-10T19:09:30-05:00 ", grpavp_sub1);
			EN_GRPAVP_U32_("Change-Condition", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub1);
			EN_GRPAVP_U32_("Diagnostics", SH_VND_ID, dict_obj_tmp, 3, grpavp_sub1);
	
			CHECK_FCT_DO( fd_msg_avp_add( grpavp, MSG_BRW_LAST_CHILD, grpavp_sub1 ), goto out  );
		}


		CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, grpavp ), goto out  );
		
		LOG_D("fj CCR Service-Information Ok\n");
	}


	/* Service-Identifier */
	EN_AVP_U32(service_identifier, 65534, req, "fj CCR Service-Identifier");

    /* Multiple-Services-Indicator */
	EN_AVP_U32(multiple_services_indicator, 1, req, "fj CCR Multiple-Services-Indicator");

	/* Multiple-Services-Credit-Control */
	{
		CHECK_FCT_DO( fd_msg_avp_new ( multiple_services_credit_control, 0, &grpavp ), goto out);

		/* Requested-Service-Unit */
		{
			CHECK_FCT_DO( fd_msg_avp_new ( requested_service_unit, 0, &grpavp_sub1 ), goto out);
		
			EN_GRPAVP_U32_("CC-Time", 0, dict_obj_tmp, 60, grpavp_sub1)

			CHECK_FCT_DO( fd_msg_avp_add( grpavp, MSG_BRW_LAST_CHILD, grpavp_sub1 ), goto out);
		}
		
		/* Used-Service-Unit */
		struct dict_object* used_service_unit = NULL;
		SEARCH_AVP_("Used-Service-Unit", 0, &used_service_unit);
		{
			CHECK_FCT_DO( fd_msg_avp_new ( used_service_unit, 0, &grpavp_sub1 ), goto out);
		
			EN_GRPAVP_U32_("CC-Time", 0, dict_obj_tmp, 0, grpavp_sub1)

			CHECK_FCT_DO( fd_msg_avp_add( grpavp, MSG_BRW_LAST_CHILD, grpavp_sub1 ), goto out);
		}

		EN_GRPAVP_U32("Reporting-Reason", SH_VND_ID, reporting_reason, 0);

		CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, grpavp ), goto out  );
	}

	/* CC-Correlation-Id */

	/* User-Equipment-Info */
	



	#if 0
    switch(gx_sm->state) {

     case STATE_INIT:

	{
	//Set Bearer-Usage
    //TODO Change this to use  enum object
       CHECK_FCT_DO( fd_msg_avp_new ( bearer_usage, 0, &avp ), goto out  );
	val.i32 = 1;//IMS
	       CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
	} 
       {
	//Set Packet Filter Operation 
	//TODO Change this to use  enum object
       CHECK_FCT_DO( fd_msg_avp_new ( pflt_oper, 0, &avp ), goto out  );
	val.i32 = 1;//ADDITION
	       CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
	 } 
	struct avp *flt_info = NULL; 
	{
	    //Set Packet Filter Information 
	   CHECK_FCT_DO( fd_msg_avp_new ( pflt_info, 0, &flt_info ), goto out  );

   
	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, flt_info ), goto out  );
	} 
	// Set Packet Filter Identity
	{

	 CHECK_FCT_DO( fd_msg_avp_new ( pflt_id, 0, &avp ), goto out  );
	  val.os.data = (unsigned char *)("ID");
		 val.os.len  = strlen("ID");
	  CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
	  if(flt_info) {
		   CHECK_FCT_DO( fd_msg_avp_add( flt_info, MSG_BRW_LAST_CHILD, avp ), goto out  );
	   }else {
		printf("flt_info NULL\n");
	    }

	 }
	
	CHECK_FCT(fd_sess_state_store(g_hdlr, sess, &gx_sm));

	break;
     case STATE_FINAL:
	 {
	//Set Packet Filter Operation 
	//TODO Change this to use  enum object
       CHECK_FCT_DO( fd_msg_avp_new ( term_cause, 0, &avp ), goto out  );
	val.i32 = 1;//Diameter logout
	       CHECK_FCT_DO( fd_msg_avp_setvalue( avp, &val ), goto out  );
	       CHECK_FCT_DO( fd_msg_avp_add( req, MSG_BRW_LAST_CHILD, avp ), goto out  );
	 } 
	break;
     default: 
	printf("State mismatch \n");
    }
	#else
	/* fj added 20160828: this allow send more than once */
	// CHECK_FCT(fd_sess_state_store(g_hdlr, sess, &gx_sm));
	#endif
	fflush(stderr);

	/* Send the request */
	printf("CCA %p\n",req);
	// Everthing Done Store the state: reply should retreive it 
	CHECK_FCT_DO( fd_msg_send( &req, gx_rec_cca, NULL ), goto out );

out:
	return 0;
}

/* Dummy ccr which :
   Read the cc-req-type && cc-req-number from the msg and stick it back
  in the reply

*/
int 	gx_handle_ccr_from_client_getport(char *cxt_id,  struct gy_msg *gy_ptr)
{
	int	sh_port, app_port=INVALID_GY_PORT;
	struct gy_port	*gy_port_ptr = NULL;

	gx_stat_increase_recv_ccr(gy_ptr->request_type);	
	
	if(gy_ptr->request_type == RT_INITIAL_REQUEST ||
		gy_ptr->request_type == RT_EVENT_REQUEST)
	{
		sh_port = gy_assign_port(cxt_id);
		if(sh_port == INVALID_GY_PORT)
		{
			return INVALID_GY_PORT;
		}
			
		gy_port_ptr = &gy_space.gy_port[sh_port];
		gy_port_ptr->service_type = gy_ptr->service_type;
	}
	else
	{
		gy_port_ptr = gy_get_port_by_cxt_id(cxt_id);
		if((gy_port_ptr == NULL) || (gy_port_ptr->used_flag == 0))
		{
			return INVALID_GY_PORT;
		}
		
		sh_port = gy_port_ptr->index;
		app_port = gy_port_ptr->app_port;
	}

	gy_ptr->app_port = app_port;
	gy_ptr->fd_port    = sh_port;

	gy_port_ptr->service_type = gy_ptr->service_type;

	return sh_port;
}

int gx_handle_cca_from_server(struct gy_msg *gy_ptr)
{
	gx_send_cca(gy_ptr);
	
	return 1;
}

int gx_send_ccr_from_client(struct gy_msg *gy_ptr)
{
	int	sh_port, app_port=INVALID_GY_PORT;
	int   retval = 0;
	struct gy_port	*gy_port_ptr = NULL;

	app_port = gy_ptr->app_port;
	if(gy_ptr->request_type == RT_INITIAL_REQUEST ||
		gy_ptr->request_type == RT_EVENT_REQUEST)
	{
		char	context_id[32];
		sprintf(context_id, "%d", app_port);
		sh_port = gy_assign_port(context_id);
		if(sh_port == INVALID_GY_PORT)
		{
			return 0;
		}
		
		gy_port_ptr = &gy_space.gy_port[sh_port];
		gy_port_ptr->app_port = app_port;

		gy_port_ptr->service_type = gy_ptr->request_type;
		gy_port_ptr->as_client = 1;
		fd_sess_destroy(&gy_sess[sh_port]);
		gy_sess[sh_port] = NULL;
	}
	else
	{
		sh_port = gy_ptr->fd_port;
		if(sh_port >= INVALID_GY_PORT)
			return 0;
		gy_port_ptr = &gy_space.gy_port[sh_port];
	}

	gy_ptr->app_port = app_port;
	gy_ptr->fd_port    = sh_port;
	gy_ptr->request_number = gy_port_ptr->request_number++;
	gy_port_ptr->service_type = gy_ptr->service_type;	
	
	retval = gx_sig_hdlr_app(gy_ptr);

	if(pps_debug_flag_for_fd())
	{
		char tmp_info[1024];
		
		sprintf(tmp_info, "[fd=%04d][app=%04d], ts=%ld.%03ld, %s \r\nmsg_type=%d, result=%d, cxt_id=%s\r\n",
			sh_port, app_port, ts_sec, ts_msec, __FUNCTION__, 
			gy_ptr->request_type, retval, gy_port_ptr->context_id);

		pps_debug_info("diameter", tmp_info);
	}
	
	return 1;
}

int gx_release_port_for_timerout(unsigned short pid)
{
	_gy_port 	*gy_port = NULL;

	gy_port = gy_get_port_space(pid);
	if(gy_port == NULL)
		return 0;

	if(0)
	{
		char tmp_info[1024];
		
		printf(" [fd=%04d][app=%04d], ts=%ld.%03ld, %s \r\n",
			pid, gy_port->app_port, ts_sec, ts_msec, __FUNCTION__);
		pps_debug_info("diameter", tmp_info);				
		
	}

	CHECK_POSIX_DO( pthread_mutex_lock(&gy_port_lock), { ASSERT(0); } );
	if(1)
	{
		gy_port_init(gy_port, pid);
		gy_space.used_ports --;
	}
	else
	{
		gy_release_port(pid);
	}
	CHECK_POSIX_DO( pthread_mutex_unlock(&gy_port_lock), { ASSERT(0); } );
	
	return 1;
}

static int gx_rec_ccr( struct msg ** msg, struct avp * r_avp, struct session * sess, void * opaque, enum disp_action * act)
{
	//struct msg *tmp_ccr_msg_ptr;
	//struct msg *tmp_ccr_msg_ptr_ptr;

	struct msg *ans, *qry;
	struct avp *avp = NULL;
	struct avp *grpavp = NULL;
	struct avp *grpavp_sub1 = NULL;
	union avp_value val;
	// struct avp *avp  = NULL;
	// struct avp_hdr * avp_data;
	int rc  = - 1;
	int fd_port = -1;
	struct gy_msg   gy_msg;
	struct gy_msg *gy_ptr=&gy_msg;

	LOG_D("%p %p %p %p", msg, r_avp, sess, act);
       
	if (msg == NULL)
		return EINVAL;

	fprintf(stderr, "ECHO ccr rec from done...\n");
	
	LOG_D("fj gx_rec_ccr enter");

	memset(gy_ptr, 0x00, sizeof(_gy_msg));
	gy_ptr->msg_type = GY_MSG_CCR;

#if _TEST_CCA
	gx_send_cca_test();
#else
	gx_parse_ccr(msg, gy_ptr);
#endif 


	CHECK_FCT_DO( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) , goto out);

	/*
	tmp_ccr_msg_ptr		= *msg;
	tmp_ccr_msg_ptr_ptr	= msg;
	*/
		
	*act = DISP_ACT_ERROR + 1;
	
	fd_port = gx_handle_ccr_from_client_getport(gy_ptr->cxt_id, gy_ptr);

	if (pps_debug_flag_for_fd())
	{
		char tmp_buf[256];

		sprintf(tmp_buf, "CCR received with context id=%s, fd_port=%d, app_port=%d", 
			gy_ptr->cxt_id, fd_port, gy_ptr->app_port);
		pps_debug_info("diameter", tmp_buf);
	}

	if(fd_port >= INVALID_GY_PORT )
	{
		// add CCA fail========================================
		gy_ptr->fd_port = INVALID_GY_PORT;
		gy_ptr->app_port = INVALID_GY_PORT;
		gy_ptr->msg_type = GY_MSG_CCA;
		gy_ptr->msg_body.cca.result = 4010;
		gy_ptr->msg_body.cca.check_balance_result = CBR_NO_CREDIT;
		gy_ptr->msg_body.cca.grant_value = 0;
		gy_ptr->msg_body.cca.volume_threshold = 0;
		gy_ptr->msg_body.cca.time_threshold = 0;
		gy_ptr->msg_body.cca.is_final = 0;
		g_direct_cca_fail_msg_ptr = *msg;
		gx_send_cca_fail(gy_ptr);// response CCA
		//

		return 0;
	}

	//CHECK_FCT_DO( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) , goto out);

	if(fd_port != INVALID_GY_PORT )
	{
		g_ccr_msg_ptr[fd_port] = *msg;
		//g_ccr_msg_ptr_ptr[fd_port] = msg;
	}

	//pps_recv_gy_process(gy_ptr);
	pps_ro_gy_cb(gy_ptr);
	/*pthread_mutex_lock( &gy_msg_mtx );
	gx_add_msg_to_list(gy_ptr);
	pthread_mutex_unlock( &gy_msg_mtx );*/
	
	rc  = 0;

	return rc;
	
	/* Create answer header */
	qry = *msg;
	CHECK_FCT_DO( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) , goto out);
	ans = *msg;

	/* set application id */
	{
		struct msg_hdr * msg_hdr = NULL;
		ASSERT( 0 == fd_msg_hdr ( ans, &msg_hdr ) );
		msg_hdr->msg_appl = SH_APP_ID;
		msg_hdr->msg_flags = msg_hdr->msg_flags & (~CMD_FLAG_PROXIABLE);
	}

	/* Set the Origin-Host, Origin-Realm, Result-Code AVPs */
	CHECK_FCT_DO( fd_msg_rescode_set( ans, "DIAMETER_SUCCESS", NULL, NULL, 1 ), goto out );

	// Get the auth_app_id and from the reply and set it in the reply 
	CHECK_FCT_DO(dcca_ans_from_req( auth_app_id, qry, msg), goto out);
	CHECK_FCT_DO(dcca_ans_from_req( cc_req_type, qry, msg), goto out);
	CHECK_FCT_DO(dcca_ans_from_req( cc_req_num, qry, msg), goto out);

	/* Multiple-Services-Credit-Control */
	{
		CHECK_FCT_DO( fd_msg_avp_new ( multiple_services_credit_control, 0, &grpavp ), goto out  );

		/* Result-Code */
		struct dict_object *result_code = NULL;
		EN_GRPAVP_U32("Result-Code", 0, result_code, 2001);
		
		/* Granted-Service-Unit */
		struct dict_object *granted_service_unit = NULL;
		SEARCH_AVP_("Granted-Service-Unit", 0, &granted_service_unit);
		{
			CHECK_FCT_DO( fd_msg_avp_new ( granted_service_unit, 0, &grpavp_sub1 ), goto out  );
		
			EN_GRPAVP_U32_("CC-Time", 0, cc_time, 120, grpavp_sub1)

			CHECK_FCT_DO( fd_msg_avp_add( grpavp, MSG_BRW_LAST_CHILD, grpavp_sub1 ), goto out  );
			
			LOG_D("fj CCR Granted-Service-Unit Ok\n");
		}

		CHECK_FCT_DO( fd_msg_avp_add( ans, MSG_BRW_LAST_CHILD, grpavp ), goto out  );
		
		LOG_D("fj CCR Multiple-Services-Credit-Control Ok\n");
	}

	/* Send the answer */
	CHECK_FCT_DO( fd_msg_send( msg, NULL, NULL ), goto out );
	rc  = 0;
out:

	LOG_D("fj gx_rec_ccr rc:%d exit", rc);
	
    //Free up the memory
    return rc ;
}

static void gx_rec_cca(void *para, struct msg **msg)
{
	LOG_D("fj gx_rec_cca enter");

	gx_parse_cca(msg);

	CHECK_FCT_DO( fd_msg_free( *msg), return);
	*msg = NULL;
	
	LOG_D("fj gx_rec_cca exit");
}

int	gx_stat_clean_all()
{
	memset(&gy_stat, 0x00, sizeof(gy_stat));
	
	return 1;
}

int	gx_stat_increase_recv_ccr(int type)
{
	gy_stat.recv_stat.ccr ++;
	switch(type)
	{
		case RT_INITIAL_REQUEST:
			gy_stat.recv_stat.ccr_init ++;
		break;
		case RT_UPDATE_REQUEST:
			gy_stat.recv_stat.ccr_update ++;
		break;
		case RT_TERMINATE_REQUEST:
			gy_stat.recv_stat.ccr_terminate ++;
		break;
		case RT_EVENT_REQUEST:
			gy_stat.recv_stat.ccr_event ++;			
		break;
	}

	return 1;
}

int	gx_stat_increase_send_ccr(int type)
{
	gy_stat.send_stat.ccr ++;
	switch(type)
	{
		case RT_INITIAL_REQUEST:
			gy_stat.send_stat.ccr_init ++;
		break;
		case RT_UPDATE_REQUEST:
			gy_stat.send_stat.ccr_update ++;
		break;
		case RT_TERMINATE_REQUEST:
			gy_stat.send_stat.ccr_terminate ++;
		break;
		case RT_EVENT_REQUEST:
			gy_stat.send_stat.ccr_event ++;			
		break;
	}

	return 1;
}

int	gx_stat_increase_recv_cca(int type)
{
	gy_stat.recv_stat.cca ++;
	switch(type)
	{
		case RT_INITIAL_REQUEST:
			gy_stat.recv_stat.cca_init ++;
		break;
		case RT_UPDATE_REQUEST:
			gy_stat.recv_stat.cca_update ++;
		break;
		case RT_TERMINATE_REQUEST:
			gy_stat.recv_stat.cca_terminate ++;
		break;
		case RT_EVENT_REQUEST:
			gy_stat.recv_stat.cca_event ++;			
		break;
	}

	return 1;
}

int	gx_stat_increase_send_cca(int type)
{
	gy_stat.send_stat.cca ++;
	switch(type)
	{
		case RT_INITIAL_REQUEST:
			gy_stat.send_stat.cca_init ++;
		break;
		case RT_UPDATE_REQUEST:
			gy_stat.send_stat.cca_update ++;
		break;
		case RT_TERMINATE_REQUEST:
			gy_stat.send_stat.cca_terminate ++;
		break;
		case RT_EVENT_REQUEST:
			gy_stat.send_stat.cca_event ++;
		break;
	}

	return 1;
}

int gx_print_all_port_status()
{
	int loop=0;
	FILE *fpStatus=NULL;

	fpStatus = fopen("../log/fd_state.txt","w");
	if(fpStatus == NULL)
			return 0;

	fprintf(fpStatus,"start ts=%ld, now ts=%ld\r\n", gx_start_ts, ts_sec);
			
	for(loop=0; loop<MAX_GY_PORT; loop++)
	{
		if(gy_space.gy_port[loop].used_flag == 1)
		{
			fprintf(fpStatus,"[%04d].update_ts=%ld, duration=%ld(s)\r\n",
						loop, 
						gy_space.gy_port[loop].updated_ts,
						ts_sec - gy_space.gy_port[loop].updated_ts);
			
		}
	}	
						
	fclose(fpStatus);
	
	return 1;
}

int gx_print_stat()
{
	char	  buf[1024], tmp_buf[128], buf_value[10][128];

	sprintf(buf,"%12s	%8s		%8s\r\n"," ","Send","Recv");

	sprintf(tmp_buf,"%s\r\n","--------------------------------------------------------");
	strcat(buf, tmp_buf);
	
	sprintf(buf_value[0],"%d", gy_stat.send_stat.ccr);
	sprintf(buf_value[1],"%d", gy_stat.recv_stat.ccr);
	sprintf(tmp_buf,"%12s	%8s		%8s\r\n","CCR", buf_value[0], buf_value[1]);
	strcat(buf, tmp_buf);
	
	sprintf(buf_value[0],"%d", gy_stat.send_stat.ccr_init);
	sprintf(buf_value[1],"%d", gy_stat.recv_stat.ccr_init);
	sprintf(tmp_buf,"%12s	%8s		%8s\r\n","CCR_Init", buf_value[0], buf_value[1]);
	strcat(buf, tmp_buf);

	sprintf(buf_value[0],"%d", gy_stat.send_stat.ccr_update);
	sprintf(buf_value[1],"%d", gy_stat.recv_stat.ccr_update);
	sprintf(tmp_buf,"%12s	%8s		%8s\r\n","CCR_Update", buf_value[0], buf_value[1]);
	strcat(buf, tmp_buf);

	sprintf(buf_value[0],"%d", gy_stat.send_stat.ccr_terminate);
	sprintf(buf_value[1],"%d", gy_stat.recv_stat.ccr_terminate);
	sprintf(tmp_buf,"%12s	%8s		%8s\r\n","CCR_Term", buf_value[0], buf_value[1]);
	strcat(buf, tmp_buf);

	sprintf(buf_value[0],"%d", gy_stat.send_stat.ccr_event);
	sprintf(buf_value[1],"%d", gy_stat.recv_stat.ccr_event);
	sprintf(tmp_buf,"%12s	%8s		%8s\r\n","CCR_Event", buf_value[0], buf_value[1]);
	strcat(buf, tmp_buf);

	sprintf(tmp_buf,"%s\r\n","--------------------------------------------------------");
	strcat(buf, tmp_buf);

	sprintf(buf_value[0],"%d", gy_stat.send_stat.cca);
	sprintf(buf_value[1],"%d", gy_stat.recv_stat.cca);
	sprintf(tmp_buf,"%12s	%8s		%8s\r\n","CCA", buf_value[0], buf_value[1]);
	strcat(buf, tmp_buf);
	
	sprintf(buf_value[0],"%d", gy_stat.send_stat.cca_init);
	sprintf(buf_value[1],"%d", gy_stat.recv_stat.cca_init);
	sprintf(tmp_buf,"%12s	%8s		%8s\r\n","CCA_Init", buf_value[0], buf_value[1]);
	strcat(buf, tmp_buf);

	sprintf(buf_value[0],"%d", gy_stat.send_stat.cca_update);
	sprintf(buf_value[1],"%d", gy_stat.recv_stat.cca_update);
	sprintf(tmp_buf,"%12s	%8s		%8s\r\n","CCA_Update", buf_value[0], buf_value[1]);
	strcat(buf, tmp_buf);

	sprintf(buf_value[0],"%d", gy_stat.send_stat.cca_terminate);
	sprintf(buf_value[1],"%d", gy_stat.recv_stat.cca_terminate);
	sprintf(tmp_buf,"%12s	%8s		%8s\r\n","CCA_Term", buf_value[0], buf_value[1]);
	strcat(buf, tmp_buf);

	sprintf(buf_value[0],"%d", gy_stat.send_stat.cca_event);
	sprintf(buf_value[1],"%d", gy_stat.recv_stat.cca_event);
	sprintf(tmp_buf,"%12s	%8s		%8s\r\n","CCA_Event", buf_value[0], buf_value[1]);
	strcat(buf, tmp_buf);


	pps_debug_info("diameter", buf);
	
	return 1;
}

int  gx_clear_all_port_for_timeout()
{
	static int fd_timer_counter = 0;
	register int fd_loop=0;
	int	index;
	long	updated_ts=0;	

	if(fd_timer_counter ++ % 100)//every second
		return 0;
	
	for(fd_loop=0; fd_loop<MAX_GY_PORT; fd_loop++)
	{
		index = fd_loop;
		if(gy_space.gy_port[index].used_flag == 1)
		{
			updated_ts = gy_space.gy_port[index].updated_ts; 
			
			if(gy_space.gy_port[index].as_client == 1)
			{
				if(gy_space.gy_port[index].service_type == ST_CS_SMS)
				{
					if( (ts_sec - updated_ts ) > 10) //timeout for SMS
					{
						gx_release_port_for_timerout(index);
					}
				}
				else
				{
					if( ( ts_sec - updated_ts ) >1800 ) //half hour
					{
						gx_release_port_for_timerout(index);
					}
				}
			}
			else
			{
				if(( ts_sec - updated_ts) > 1800) //half hour
				{
					gx_release_port_for_timerout(index);
				}
			}
		}
	}	

	return 1;
}

int gx_fsm(long sec, int msec)
{	
	ts_sec = sec;
	ts_msec = msec;
	if(gx_start_ts<=1)
		gx_start_ts = sec;

	return gx_clear_all_port_for_timeout();
}

// *********************************************************************
/*#define MAX_GY_MSG_NUM  8192
#define MAX_HANDLED_GY_MSG_PER_CYCLE  100
typedef struct
{
	unsigned int header;
	unsigned int tailer;
	_gy_msg msg[MAX_GY_MSG_NUM];
}GY_MSG_LIST;

GY_MSG_LIST gy_msg_list = {0, 0, };

static int gx_add_msg_to_list(_gy_msg *pInMsg)
{
    _gy_msg *pMsg = NULL;
    
    if (pInMsg == NULL)
    {
        return -1;
    }

    if(((gy_msg_list.tailer+1) % MAX_GY_MSG_NUM) == gy_msg_list.header)
    {
        return -1;
    }

    pMsg = &gy_msg_list.msg[gy_msg_list.tailer];
    memcpy(pMsg, pInMsg, sizeof(_gy_msg));
    
    gy_msg_list.tailer = (gy_msg_list.tailer+1) % MAX_GY_MSG_NUM;

    return 0;
}


static int gx_get_msg_from_list(_gy_msg *pOutMsg)
{
    _gy_msg *pMsg = NULL;

    if (pOutMsg == NULL)
    {
        return -1;
    }

    if (gy_msg_list.header != gy_msg_list.tailer)
    {
        pMsg = &gy_msg_list.msg[gy_msg_list.header];
        memcpy(pOutMsg, pMsg, sizeof(_gy_msg));

        gy_msg_list.header = (gy_msg_list.header+1) % (MAX_GY_MSG_NUM);

        return 0;
    }

    return -1;
}

void gx_handle_msg_cb()
{
    int i, ret;
    _gy_msg gy_msg, *gy_ptr;
    gy_ptr = &gy_msg;

    for (i=0; i<MAX_HANDLED_GY_MSG_PER_CYCLE; i++)
    {
	pthread_mutex_lock( &gy_msg_mtx );
        ret = gx_get_msg_from_list(gy_ptr);
	pthread_mutex_unlock( &gy_msg_mtx );

        if (ret < 0)
        {
            break;
        }
        
        pps_recv_gy_process(gy_ptr);
    }

    return ;
}*/

