#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include "../include/restapi.h"

static void _encode_u64(u8 *buf, int *len, const u64 val)
{
	*(u32*)(&buf[*len]) = htonl((val >> 32) & 0xFFFFFFFF);
	*len += 0x04;
	*(u32*)(&buf[*len]) = htonl(val & 0xFFFFFFFF);
	*len += 0x04;
}

static u64 _decode_u64(u8 *buf)
{
	u64 val = 0;
	val = ntohl( *(u32*)(&buf[0]) );
	val = val << 32;
	val += ntohl( *(u32*)(&buf[4]) ) & 0xffffffff;

	return val;
}


#define ENCODE_HEADER() \
do{ \
	buf[len++] = ptr->msg_type;	\
	buf[len++] = IE_SRC_REF;	\
	buf[len++] = 0x02;		\
	*(u16*)(&buf[len]) = htons(ptr->header.src_ref); \
	len += 2;			\
	buf[len++] = IE_DST_REF;	\
	buf[len++] = 0x02;		\
	*(u16*)(&buf[len]) = htons(ptr->header.dst_ref); \
	len += 2;			\
}while(0)

int encode_rest_query(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();
	
	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.query.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.query.msisdn);
	len += vallen;
	
	return len;
}

static int decode_rest_query(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			memcpy(ptr->msg.query.msisdn, &buf[offset], vallen);
			ptr->msg.query.msisdn[vallen] = '\0';
			break;
		case IE_RESULT: 
			ptr->msg.query_res.result = buf[offset];
			break;
		case IE_ERROR_CODE:
			ptr->msg.query_res.error_code = buf[offset];
			break;
		case IE_BALANCE:
			ptr->msg.query_res.balance = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_MO_EXPIRY:
			ptr->msg.query_res.mo_expiry = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_MT_EXPIRY:
			ptr->msg.query_res.mt_expiry = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_USERNAME:
			{
				memcpy(ptr->msg.topup.username, &buf[offset], vallen);
				ptr->msg.topup.username[vallen] = '\0';
			}
			break;
		case IE_PASSWORD:
			{
				memcpy(ptr->msg.topup.password, &buf[offset], vallen);
				ptr->msg.topup.password[vallen] = '\0';
			}
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

int encode_rest_query_res(_rest_msg_s *ptr, u8 *buf)
{
	int len=0/*, vallen=0*/;
	
	ENCODE_HEADER();
	
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.query_res.result;
	if(ptr->msg.query_res.result == 1)
	{
		buf[len++] = IE_ERROR_CODE;
		buf[len++] = 0x01;
		buf[len++] = ptr->msg.query_res.error_code;
		
		return len;
	}

	buf[len++] = IE_BALANCE;
	buf[len++] = 0x04;
	// memcpy(&buf[len], &ptr->msg.query_res.balance, 0x04);
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_res.balance);
	len += 0x04;

	buf[len++] = IE_MO_EXPIRY;
	buf[len++] = 0x04;
	// memcpy(&buf[len], &ptr->msg.query_res.mo_expiry, 0x04);
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_res.mo_expiry);
	len += 0x04;

	buf[len++] = IE_MT_EXPIRY;
	buf[len++] = 0x04;
	// memcpy(&buf[len], &ptr->msg.query_res.mt_expiry, 0x04);
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_res.mt_expiry);
	len += 0x04;
	
	return len;
}

int encode_rest_topup(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();

	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.topup.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.topup.msisdn);
	len += vallen;

	buf[len++] = IE_USERNAME;
	vallen = strlen(ptr->msg.topup.username);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.topup.username);
	len += vallen;
	

	buf[len++] = IE_PASSWORD;
	vallen = strlen(ptr->msg.topup.password);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.topup.password);
	len += vallen;

    if (strlen(ptr->msg.topup.pincode)>0)
    {
        buf[len++] = IE_PINCODE;
        vallen = strlen(ptr->msg.topup.pincode);
        buf[len++] = vallen;
        strcpy((char*)( &buf[len] ), ptr->msg.topup.pincode);
        len += vallen;
    }

	if((ptr->msg.topup.optional_flag & 0x01) == 0x01)
	{
		buf[len++] = IE_ACCOUNT_ID;
		vallen = 4;
		buf[len++] = vallen;
		*(u32*)(&buf[len]) = htonl(ptr->msg.topup.account_id);
		len += vallen;
		
	}

	if((ptr->msg.topup.optional_flag & 0x02) == 0x02)
	{
		buf[len++] = IE_BALANCE_AVAILABLE;
		vallen = 4;
		buf[len++] = vallen;
		*(u32*)(&buf[len]) = htonl(ptr->msg.topup.balance);
		len += vallen;
		
	}
	
	
	return len;
}

int encode_rest_order(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();

	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.order.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.order.msisdn);
	len += vallen;

	buf[len++] = IE_SERVICE_TYPE;
	vallen = 4;
	buf[len++] = vallen;
	*(u32*)(&buf[len]) = htonl(ptr->msg.order.busicode);
	len += vallen;
	
	buf[len++] = IE_BUNDLE_ID;
	vallen = 4;
	buf[len++] = vallen;
	*(u32*)(&buf[len]) = htonl(ptr->msg.order.offer_id);
	len += vallen;

	buf[len++] = IE_PAY_TYPE;
	vallen = 4;
	buf[len++] = vallen;
	*(u32*)(&buf[len]) = htonl(ptr->msg.order.paymethod);
	len += vallen;

    if (ptr->msg.order.busicode == 1000)// airtime recharge
    {
		buf[len++] = IE_RECHARGE_AMOUNT;
		buf[len++] = 0x04;
		*(u32*)(&buf[len]) = htonl(ptr->msg.order.balance);
		len += 0x04;
    }

    if ((ptr->msg.order.paymethod & 0xff) == 10 && strlen(ptr->msg.order.pincode) > 0)
    {
    	buf[len++] = IE_PINCODE;
    	vallen = strlen(ptr->msg.order.pincode);
    	buf[len++] = vallen;
        memcpy(&buf[len], ptr->msg.order.pincode, vallen);
    	len += vallen;
    }

    if (ptr->msg.order.payMsisdn[0] != '\0')
    {
    	buf[len++] = IE_MSISDN_TRANS_OUT;
    	vallen = strlen(ptr->msg.order.payMsisdn);
    	buf[len++] = vallen;
        memcpy(&buf[len], ptr->msg.order.payMsisdn, vallen);
    	len += vallen;
    }

    if (ptr->msg.order.callerMsisdn[0] != '\0')
    {
    	buf[len++] = IE_CALLER_NUMBER;
    	vallen = strlen(ptr->msg.order.callerMsisdn);
    	buf[len++] = vallen;
        memcpy(&buf[len], ptr->msg.order.callerMsisdn, vallen);
    	len += vallen;
    }

	return len;
}

int encode_rest_free_resource(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();

	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.free_resource.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.free_resource.msisdn);
	len += vallen;

	return len;
}

int encode_rest_downloadApp(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();

	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.downloadApp.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.downloadApp.msisdn);
	len += vallen;

	return len;
}

int encode_rest_offerChange(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();

	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.offerChange.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.offerChange.msisdn);
	len += vallen;

	buf[len++] = IE_SERVICE_TYPE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl((u32)(ptr->msg.offerChange.opt_out));
	len += 0x04;

	return len;
}

int encode_rest_queryPoint(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();

	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.queryPoint.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.queryPoint.msisdn);
	len += vallen;

	return len;
}

int encode_rest_transferPoint(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();

	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.transferPoint.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.transferPoint.msisdn);
	len += vallen;

	buf[len++] = IE_MSISDN_TRANS_IN;
	vallen = strlen(ptr->msg.transferPoint.target_msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.transferPoint.target_msisdn);
	len += vallen;

	buf[len++] = IE_AMOUNT;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.transferPoint.amount);
	len += 0x04;

	buf[len++] = IE_SERVICE_TYPE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.transferPoint.busicode);
	len += 0x04;

	return len;
}

int encode_rest_channel(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();

	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.chnl.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.chnl.msisdn);
	len += vallen;

	buf[len++] = IE_USERNAME;
	vallen = strlen(ptr->msg.chnl.sess_id);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.chnl.sess_id);
	len += vallen;

	buf[len++] = IE_REMARK;
	vallen = strlen(ptr->msg.chnl.sc_url);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.chnl.sc_url);
	len += vallen;

    if (strlen(ptr->msg.chnl.input)>0)
    {
        buf[len++] = IE_MSG_CONTENT;
        vallen = strlen(ptr->msg.chnl.input);
        buf[len++] = vallen;
        strcpy((char*)( &buf[len] ), ptr->msg.chnl.input);
        len += vallen;
    }
	
	return len;
}

static int decode_rest_channel_res(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_RESULT: 
			{
				ptr->msg.chnl_res.result = buf[offset];
			}
			break;
		case IE_ERROR_CODE:
			{
				ptr->msg.chnl_res.error_code = buf[offset];
			}
			break;
		case IE_STATUS:
			{
				ptr->msg.chnl_res.sess_state = buf[offset];
			}
			break;
		case IE_MSG_CONTENT:
			{
				memcpy(ptr->msg.chnl_res.prompt, &buf[offset], vallen);
				ptr->msg.chnl_res.prompt[vallen] = '\0';
			}
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_queryPoint_res(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_RESULT: 
			{
				ptr->msg.queryPoint_res.result = buf[offset];
			}
			break;
		case IE_ERROR_CODE:
			{
				ptr->msg.queryPoint_res.error_code = buf[offset];
			}
			break;
		case IE_AMOUNT:
			{
				ptr->msg.queryPoint_res.amount = ntohl( *(u32*)(&buf[offset]) );
			}
			break;
		case IE_BALANCE_AVAILABLE:
			{
				ptr->msg.queryPoint_res.airtime_amount = ntohl( *(u32*)(&buf[offset]) );
			}
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_transferPoint_res(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_RESULT: 
			{
				ptr->msg.queryPoint_res.result = buf[offset];
			}
			break;
		case IE_ERROR_CODE:
			{
				ptr->msg.queryPoint_res.error_code = buf[offset];
			}
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_topup(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			{
				memcpy(ptr->msg.topup.msisdn, &buf[offset], vallen);
				ptr->msg.topup.msisdn[vallen] = '\0';
			}
			break;
		case IE_ACCOUNT_ID:
			{
				ptr->msg.topup.account_id = ntohl( *(u32*)(&buf[offset]) );
				ptr->msg.topup.optional_flag |= 0x01;
			}
			break;		
		case IE_BALANCE_AVAILABLE:
			{
				ptr->msg.topup.balance = ntohl( *(u32*)(&buf[offset]) );
				ptr->msg.topup.optional_flag |= 0x02;
			}
			break;
			
		case IE_RESULT: 
			{
				ptr->msg.topup_res.result = buf[offset];
			}
			break;
		case IE_ERROR_CODE:
			{
				ptr->msg.topup_res.error_code = buf[offset];
			}
			break;
		case IE_BALANCE:
			{
				ptr->msg.topup_res.balance = ntohl( *(u32*)(&buf[offset]) );
			}
			break;
		case IE_MO_EXPIRY:
			{
				ptr->msg.topup_res.mo_expiry = ntohl( *(u32*)(&buf[offset]) );
			}
			break;
		case IE_MT_EXPIRY:
			{
				ptr->msg.topup_res.mt_expiry = ntohl( *(u32*)(&buf[offset]) );
			}
			break;
		case IE_USERNAME:
			{
				memcpy(ptr->msg.topup.username, &buf[offset], vallen);
				ptr->msg.topup.username[vallen] = '\0';
			}
			break;
		case IE_PASSWORD:
			{
				memcpy(ptr->msg.topup.password, &buf[offset], vallen);
				ptr->msg.topup.password[vallen] = '\0';
			}
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

int encode_rest_topup_res(_rest_msg_s *ptr, u8 *buf)
{
	return encode_rest_query_res(ptr, buf);		
}

int decode_rest_transfer_res(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_RESULT: 
			{
				ptr->msg.transfer_rsp.result = buf[offset];
			}
			break;
		case IE_ERROR_CODE:
			{
				ptr->msg.transfer_rsp.error_code = buf[offset];
			}
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

// for selfcare======================================
int encode_rest_send_authcode_req(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();

	// IE_MSISDN
	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.send_authcode_req.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.send_authcode_req.msisdn);
	len += vallen;

	// IE_MSG_CONTENT
	buf[len++] = IE_MSG_CONTENT;
	vallen = strlen(ptr->msg.send_authcode_req.sms_content);
	buf[len++] = vallen >> 8;
	buf[len++] = vallen & 0xff;
	strcpy((char*)( &buf[len] ), ptr->msg.send_authcode_req.sms_content);
	len += vallen;
	
	return len;
}

int encode_rest_send_authcode_rsp(_rest_msg_s *ptr, u8 *buf)
{
	int len=0/*, vallen=0*/;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.send_authcode_rsp.result;
	
	// IE_ERROR_CODE
	buf[len++] = IE_ERROR_CODE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.send_authcode_rsp.error_code);
	len += 0x04;

	return len;
}


int encode_rest_query_user_data_req(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();
	
	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.query_user_data_req.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.query_user_data_req.msisdn);
	len += vallen;
	
	return len;
}

int encode_rest_query_user_data_rsp(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.query_user_data_rsp.result;
	
	// IE_ERROR_CODE
	buf[len++] = IE_ERROR_CODE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_user_data_rsp.error_code);
	len += 0x04;

	// IE_MSISDN
	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.query_user_data_rsp.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.query_user_data_rsp.msisdn);
	len += vallen;
	//
	
	// IE_REMARK
	buf[len++] = IE_REMARK;
	vallen = strlen(ptr->msg.query_user_data_rsp.remark);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.query_user_data_rsp.remark);
	len += vallen;
	//
	
	// IE_GROUP_NAME
	buf[len++] = IE_GROUP_NAME;
	vallen = strlen(ptr->msg.query_user_data_rsp.usrGrpName);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.query_user_data_rsp.usrGrpName);
	len += vallen;
	//
	
	// IE_STATUS
	buf[len++] = IE_STATUS;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.query_user_data_rsp.status;
	//

	// IE_BALANCE
	buf[len++] = IE_BALANCE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_user_data_rsp.balance);
	len += 0x04;
	//

	// IE_EXPIRY_TIME
	buf[len++] = IE_EXPIRY_TIME;
	buf[len++] = 0x08;
	*(u32*)(&buf[len]) = htonl((ptr->msg.query_user_data_rsp.mo_expiry >> 32) & 0xFFFFFFFF);
	len += 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_user_data_rsp.mo_expiry & 0xFFFFFFFF);
	len += 0x04;
	//
	
	// IE_REMAIN_MO_VOICE_MIN
	buf[len++] = IE_REMAIN_MO_VOICE_MIN;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_user_data_rsp.remain_mo_voc_min);
	len += 0x04;
	//
	
	// IE_REMAIN_MT_VOICE_MIN
	buf[len++] = IE_REMAIN_MT_VOICE_MIN;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_user_data_rsp.remain_mt_voc_min);
	len += 0x04;
	//
	
	// IE_REMAIN_SMS_NUM
	buf[len++] = IE_REMAIN_SMS_NUM;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_user_data_rsp.remain_sms_num);
	len += 0x04;
	//
	
	// IE_REMAIN_DATA_VOL_MB
	buf[len++] = IE_REMAIN_DATA_VOL_MB;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_user_data_rsp.remain_data_vol);
	len += 0x04;
	//
	
	return len;
}

int encode_rest_bundle_subs_req(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();
	
	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.bundle_subs_req.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.bundle_subs_req.msisdn);
	len += vallen;
	
	// IE_PAY_TYPE
	buf[len++] = IE_PAY_TYPE;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.bundle_subs_req.payType;
	//

	// IE_AMOUNT
	buf[len++] = IE_AMOUNT;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_subs_req.charge);
	len += 0x04;
	//

	// IE_MO_VOICE_MIN
	buf[len++] = IE_MO_VOICE_MIN;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_subs_req.moVoiceMinute);
	len += 0x04;
	//
	
	// IE_MT_VOICE_MIN
	buf[len++] = IE_MT_VOICE_MIN;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_subs_req.mtVoiceMinute);
	len += 0x04;
	//
	
	// IE_SMS_NUM
	buf[len++] = IE_SMS_NUM;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_subs_req.smsNum);
	len += 0x04;
	//
	
	// IE_DATA_VOL_MB
	buf[len++] = IE_DATA_VOL_MB;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_subs_req.dataVolume);
	len += 0x04;
	//
	
	// IE_VALID_DAYS
	buf[len++] = IE_VALID_DAYS;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_subs_req.validDays);
	len += 0x04;
	//
	
	return len;
}

int encode_rest_bundle_subs_rsp(_rest_msg_s *ptr, u8 *buf)
{
	int len=0;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.bundle_subs_rsp.result;

	// IE_ERROR_CODE
	buf[len++] = IE_ERROR_CODE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_subs_rsp.error_code);
	len += 0x04;

	return len;
}

int encode_rest_bundle_usage_req(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();
	
	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.bundle_usage_req.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.bundle_usage_req.msisdn);
	len += vallen;
	
	return len;
}

int encode_rest_bundle_usage_rsp(_rest_msg_s *ptr, u8 *buf)
{
	int len=0;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.bundle_usage_rsp.result;

	// IE_ERROR_CODE
	buf[len++] = IE_ERROR_CODE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_usage_rsp.error_code);
	len += 0x04;

	// IE_REMAIN_MO_VOICE_MIN
	buf[len++] = IE_REMAIN_MO_VOICE_SEC;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_usage_rsp.moVoiceInSec);
	len += 0x04;
	//
	
	// IE_REMAIN_MT_VOICE_MIN
	buf[len++] = IE_REMAIN_MT_VOICE_SEC;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_usage_rsp.mtVoiceInSec);
	len += 0x04;
	//
	
	// IE_REMAIN_SMS_NUM
	buf[len++] = IE_REMAIN_SMS_NUM;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_usage_rsp.smsNum);
	len += 0x04;
	//
	
	// IE_REMAIN_DATA_VOL_MB
	buf[len++] = IE_REMAIN_DATA_VOL_KB;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_usage_rsp.dataVolInKB);
	len += 0x04;
	//
	
	// IE_EXPIRY_TIME
	buf[len++] = IE_EXPIRY_TIME;
	buf[len++] = 0x08;
	*(u32*)(&buf[len]) = htonl((ptr->msg.bundle_usage_rsp.expiredTime >> 32) & 0xFFFFFFFF);
	len += 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.bundle_usage_rsp.expiredTime & 0xFFFFFFFF);
	len += 0x04;
	//
	
	return len;
}


int encode_rest_recharge_req(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();
	
	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.recharge_req.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.recharge_req.msisdn);
	len += vallen;
	
	buf[len++] = IE_AMOUNT;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.recharge_req.amount);
	len += 0x04;

	buf[len++] = IE_RECHARGE_TYPE;
	buf[len++] = 0x01;
	buf[len] =  ptr->msg.recharge_req.op_type;
	len += 0x01;

	buf[len++] = IE_VALID_DAYS;
	buf[len++] = 0x02;
	*(u16*)(&buf[len]) = htons(ptr->msg.recharge_req.valid_days);
	len += 0x02;
	
	return len;
}

int encode_rest_recharge_rsp(_rest_msg_s *ptr, u8 *buf)
{
	int len=0;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.recharge_rsp.result;

	if(ptr->msg.recharge_rsp.result == RES_FAILED)
	{
		buf[len++] = IE_ERROR_CODE;
		buf[len++] = 0x01;
		buf[len++] = ptr->msg.recharge_rsp.error_code;
		
		return len;
	}
	//

	// IE_STATUS
	buf[len++] = IE_STATUS;
	buf[len++] = 0x01;
	buf[len] = ptr->msg.recharge_rsp.status;
	len += 0x01;
	//

	// IE_BALANCE
	buf[len++] = IE_BALANCE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.recharge_rsp.balance);
	len += 0x04;
	//
	
	// IE_EXPIRY_TIME
	buf[len++] = IE_EXPIRY_TIME;
	buf[len++] = 0x08;
	*(u32*)(&buf[len]) = htonl((ptr->msg.recharge_rsp.expiredTime >> 32) & 0xFFFFFFFF);
	len += 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.recharge_rsp.expiredTime & 0xFFFFFFFF);
	len += 0x04;
	//
	
	return len;
}

int encode_rest_transfer_req(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();
	
	buf[len++] = IE_MSISDN_TRANS_OUT;
	vallen = strlen(ptr->msg.transfer_req.transferOutMsisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.transfer_req.transferOutMsisdn);
	len += vallen;
	
	buf[len++] = IE_MSISDN_TRANS_IN;
	vallen = strlen(ptr->msg.transfer_req.transferInMsisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.transfer_req.transferInMsisdn);
	len += vallen;
	
	buf[len++] = IE_AMOUNT;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.transfer_req.amount);
	len += 0x04;
	
	return len;
}

int encode_rest_transfer_rsp(_rest_msg_s *ptr, u8 *buf)
{
	int len=0;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.transfer_rsp.result;

	// IE_ERROR_CODE
	buf[len++] = IE_ERROR_CODE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.transfer_rsp.error_code);
	len += 0x04;

	buf[len++] = IE_AMOUNT;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.transfer_rsp.balance);
	len += 0x04;
	
	return len;
}

int encode_rest_recharge_card_req(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();
	
	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.recharge_card_req.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.recharge_card_req.msisdn);
	len += vallen;
	
	buf[len++] = IE_PASSWORD;
	vallen = strlen(ptr->msg.recharge_card_req.cardPwd);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.recharge_card_req.cardPwd);
	len += vallen;
	
	return len;
}

int encode_rest_recharge_card_rsp(_rest_msg_s *ptr, u8 *buf)
{
	int len=0;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.recharge_card_rsp.result;

	// IE_ERROR_CODE
	buf[len++] = IE_ERROR_CODE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.recharge_card_rsp.error_code);
	len += 0x04;

	// IE_BALANCE
	buf[len++] = IE_RECHARGE_AMOUNT;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.recharge_card_rsp.rechargeAmount);
	len += 0x04;
	//
	
	// IE_BALANCE
	buf[len++] = IE_BALANCE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.recharge_card_rsp.balance);
	len += 0x04;
	//
	
	// IE_EXPIRY_TIME
	buf[len++] = IE_EXPIRY_TIME;
	buf[len++] = 0x08;
	*(u32*)(&buf[len]) = htonl((ptr->msg.recharge_card_rsp.expiredTime >> 32) & 0xFFFFFFFF);
	len += 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.recharge_card_rsp.expiredTime & 0xFFFFFFFF);
	len += 0x04;
	//
	
	return len;
}

int encode_rest_check_balance_req(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();
	
	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.check_balance_req.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.check_balance_req.msisdn);
	len += vallen;
	
	buf[len++] = IE_AMOUNT;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.check_balance_req.amount);
	len += 0x04;
	
	return len;
}

int encode_rest_check_balance_rsp(_rest_msg_s *ptr, u8 *buf)
{
	int len=0;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.check_balance_rsp.result;

	// IE_ERROR_CODE
	buf[len++] = IE_ERROR_CODE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.check_balance_rsp.error_code);
	len += 0x04;

	// IE_BALANCE_AVAILABLE
	buf[len++] = IE_BALANCE_AVAILABLE;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.check_balance_rsp.available;
	//
	
	return len;
}

int encode_rest_query_balance_req(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;
	
	ENCODE_HEADER();
	
	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.query_balance_req.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.query_balance_req.msisdn);
	len += vallen;
	
	return len;
}

int encode_rest_query_balance_rsp(_rest_msg_s *ptr, u8 *buf)
{
	int len=0/*, vallen=0*/;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.query_balance_rsp.result;
	if(ptr->msg.query_balance_rsp.result == RES_FAILED)
	{
		buf[len++] = IE_ERROR_CODE;
		buf[len++] = 0x04;
		*(u32*)(&buf[len]) = htonl(ptr->msg.query_balance_rsp.error_code);
		len += 0x04;
		
		return len;
	}
	//

	// IE_STATUS
	buf[len++] = IE_STATUS;
	buf[len++] = 0x01;
	buf[len] = ptr->msg.query_balance_rsp.status;
	len += 1;

	// IE_BALANCE
	buf[len++] = IE_BALANCE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_balance_rsp.balance);
	len += 0x04;
	//

	// IE_BALANCE
	buf[len++] = IE_MO_EXPIRY;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_balance_rsp.mo_expiry);
	len += 0x04;
	//
	
	return len;
}

int encode_rest_sms_deliver(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;

	if(ptr == NULL || buf == NULL)
		return 0;
	
	ENCODE_HEADER();

	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.sms_deliver.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.sms_deliver.msisdn);
	len += vallen;
	
	buf[len++] = IE_SMS_CONTENT;
	vallen = strlen(ptr->msg.sms_deliver.sms_content);
	buf[len++] = vallen>>8;
	buf[len++] = vallen & 0xff;	
	strcpy((char*)( &buf[len] ), ptr->msg.sms_deliver.sms_content);
	len += vallen;
	
	return len;

}

int encode_rest_sms_deliver_res(_rest_msg_s *ptr, u8 *buf)
{
	int len=0/*, vallen=0*/;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.sms_deliver_res.result;

	buf[len++] = IE_ERROR_CODE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.sms_deliver_res.error_code);
	len += 0x04;

	
	return len;

}

int encode_rest_create_account(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;

	if(ptr == NULL || buf == NULL)
		return 0;
	
	ENCODE_HEADER();

	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.create_acct.msisdn);
	buf[len++] = vallen;
	strcpy((char*)( &buf[len] ), ptr->msg.create_acct.msisdn);
	len += vallen;

	buf[len++] = IE_CUSTOMER_ID;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.create_acct.customer_id);
	len += 0x04;

	buf[len++] = IE_ACCOUNT_ID;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.create_acct.account_id);
	len += 0x04;

	buf[len++] = IE_PRODUCT_ID;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.create_acct.product_id);
	len += 0x04;

	buf[len++] = IE_PLAN_ID;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.create_acct.plan_id);
	len += 0x04;

	buf[len++] = IE_BALANCE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.create_acct.balance);
	len += 0x04;

	buf[len++] = IE_EXPIRY_TIME;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.create_acct.expiry_date);
	len += 0x04;

	buf[len++] = IE_RENT_CHARGE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.create_acct.rent_charge);
	len += 0x04;

	buf[len++] = IE_BIRTHDAY;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.create_acct.birthday);
	len += 0x04;


	buf[len++] = IE_CUG_ID;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.create_acct.cug_id);
	len += 0x04;

	buf[len++] = IE_USER_CLASS;
	buf[len++] = 0x01;
	buf[len]  =  ptr->msg.create_acct.user_class;
	len += 0x01;
	
	return len;

}

int encode_rest_create_account_res(_rest_msg_s *ptr, u8 *buf)
{
	int len=0/*, vallen=0*/;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.create_acct_res.result;
	
	buf[len++] = IE_ERROR_CODE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.create_acct_res.error_code);
	len += 0x04;
	
	return len;

}

int encode_rest_query_tariff(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;

	if(ptr == NULL || buf == NULL)
		return 0;
	
	ENCODE_HEADER();

	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.query_tariff.msisdn);
	buf[len++] = vallen;
	strcpy((char *)&buf[len], ptr->msg.query_tariff.msisdn);
	len += vallen;

	buf[len++] = IE_SERVICE_TYPE;
	vallen = 1;
	buf[len++] = vallen;
	buf[len]= ptr->msg.query_tariff.service_type;	
	len += vallen;

	buf[len++] = IE_TARIIFF_PREFIX;
	vallen = strlen(ptr->msg.query_tariff.called_number);
	buf[len++] = vallen;
	strcpy((char *)&buf[len], ptr->msg.query_tariff.called_number);
	len += vallen;
	
	return len;

}

int encode_rest_query_tariff_res(_rest_msg_s *ptr, u8 *buf)
{
	int len= 0, vallen=0;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.query_tariff_res.result;
	if(ptr->msg.query_tariff_res.result == RES_FAILED)
	{
		buf[len++] = IE_ERROR_CODE;
		buf[len++] = 0x01;
		buf[len++] = ptr->msg.query_tariff_res.error_code;
		
		return len;
	}


	buf[len++] = IE_TARIIFF_PREFIX;
	vallen = strlen(ptr->msg.query_tariff_res.prefix);
	buf[len++] = vallen;
	strcpy((char *)&buf[len], ptr->msg.query_tariff_res.prefix);
	len += vallen;

	buf[len++] = IE_TARIFF_UNIT;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_tariff_res.unit_time);
	len += 0x04;

	buf[len++] = IE_TARIFF_CHARGE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_tariff_res.unit_charge);
	len += 0x04;

	buf[len++] = IE_TARIFF_DISCOUNT;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_tariff_res.discount);
	len += 0x04;

	buf[len++] = IE_PLAN_ID;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_tariff_res.plan_id);
	len += 0x04;
	
	buf[len++] = IE_PLAN_VALUE;
	buf[len++] = 0x08;
	_encode_u64(buf, &len, ptr->msg.query_tariff_res.total_plan_value);

	buf[len++] = IE_PLAN_USED_VALUE;
	buf[len++] = 0x08;
	_encode_u64(buf, &len, ptr->msg.query_tariff_res.used_plan_value);

	buf[len++] = IE_BUNDLE_ID;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.query_tariff_res.bundle_plan_id);
	len += 0x04;


	
	return len;

}

int encode_rest_update_subs(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;

	if(ptr == NULL || buf == NULL)
		return 0;
	
	ENCODE_HEADER();

	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.update_subs.msisdn);
	buf[len++] = vallen;
	strcpy((char *)&buf[len], ptr->msg.update_subs.msisdn);
	len += vallen;

	buf[len++] = IE_ACCOUNT_ID;
	vallen = 4;
	buf[len++] = vallen;
	*(u32*)(&buf[len]) = htonl(ptr->msg.update_subs.account_id);		
	len += vallen;

	if((ptr->msg.update_subs.optional_flag & 0x01) == 0x01)
	{
		buf[len++] = IE_STATUS;
		vallen = 1;
		buf[len++] = vallen;
		buf[len]= ptr->msg.update_subs.status;	
		len += vallen;
	}
	if((ptr->msg.update_subs.optional_flag & 0x02) == 0x02)
	{
		buf[len++] = IE_BALANCE;
		vallen = 4;
		buf[len++] = vallen;
		*(u32*)(&buf[len]) = htonl(ptr->msg.update_subs.balance);		
		len += vallen;
	}
	if((ptr->msg.update_subs.optional_flag & 0x04) == 0x04)
	{
		buf[len++] = IE_EXPIRY_TIME;
		vallen = 4;
		buf[len++] = vallen;
		*(u32*)(&buf[len]) = htonl(ptr->msg.update_subs.balance_expiry_date);		
		len += vallen;
	}

	if((ptr->msg.update_subs.optional_flag & 0x08) == 0x08)
	{
		buf[len++] = IE_PLAN_ID;
		vallen = 4;
		buf[len++] = vallen;
		*(u32*)(&buf[len]) = htonl(ptr->msg.update_subs.basic_plan_id);		
		len += vallen;
	}

	if((ptr->msg.update_subs.optional_flag & 0x10) == 0x10)
	{
		buf[len++] = IE_RENT_CHARGE;
		vallen = 4;
		buf[len++] = vallen;
		*(u32*)(&buf[len]) = htonl(ptr->msg.update_subs.basic_plan_rent);		
		len += vallen;
	}

	if((ptr->msg.update_subs.optional_flag & 0x20) == 0x20)
	{
		buf[len++] = IE_VAS_CUG_STATUS;
		vallen = 1;
		buf[len++] = vallen;
		buf[len]= ptr->msg.update_subs.vas_cug_status;	
		len += vallen;
	}
	
	
	return len;

}


int encode_rest_update_subs_res(_rest_msg_s *ptr, u8 *buf)
{
	int len= 0;//, vallen=0;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.update_subs_res.result;

	buf[len++] = IE_ERROR_CODE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.update_subs_res.error_code);
	len += 0x04;

	return len;

}


int encode_rest_delete_subs(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;

	if(ptr == NULL || buf == NULL)
		return 0;
	
	ENCODE_HEADER();

	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.delete_subs.msisdn);
	buf[len++] = vallen;
	strcpy((char *)&buf[len], ptr->msg.delete_subs.msisdn);
	len += vallen;

	buf[len++] = IE_CAUSE;
	vallen = 1;
	buf[len++] = vallen;
	buf[len]= ptr->msg.delete_subs.cause;	
	len += vallen;

	
	return len;

}

int encode_rest_delete_subs_res(_rest_msg_s *ptr, u8 *buf)
{
	int len= 0;//, vallen=0;
	
	ENCODE_HEADER();

	// IE_RESULT
	buf[len++] = IE_RESULT;
	buf[len++] = 0x01;
	buf[len++] = ptr->msg.delete_subs_res.result;

	buf[len++] = IE_ERROR_CODE;
	buf[len++] = 0x04;
	*(u32*)(&buf[len]) = htonl(ptr->msg.delete_subs_res.error_code);
	len += 0x04;

	return len;

}

int encode_rest_update_sess_info(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;

	if(ptr == NULL || buf == NULL)
		return 0;
	
	ENCODE_HEADER();

	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.update_sess_info.msisdn);
	buf[len++] = vallen;
	strcpy((char *)&buf[len], ptr->msg.update_sess_info.msisdn);
	len += vallen;

	buf[len++] = IE_SESS_FLAG;
	vallen = 1;
	buf[len++] = vallen;
	buf[len]= ptr->msg.update_sess_info.first_sess;	
	len += vallen;

	buf[len++] = IE_SERVICE_TYPE;
	vallen = 1;
	buf[len++] = vallen;
	buf[len]= ptr->msg.update_sess_info.service_type;	
	len += vallen;

	buf[len++] = IE_TIMESTAMP;
	vallen = 4;
	buf[len++] = vallen;
	*(u32*)(&buf[len]) = htonl(ptr->msg.update_sess_info.start_time);		
	len += vallen;

	{
		buf[len++] = IE_CONSUME_VALUE;
		vallen = 4;
		buf[len++] = vallen;
		*(u32*)(&buf[len]) = htonl(ptr->msg.update_sess_info.consumed_value);		
		len += vallen;		
	}

	if((ptr->msg.update_sess_info.optional_flag & 0x01) == 0x01)
	{
		buf[len++] = IE_CALLED_NUMBER;
		vallen = strlen(ptr->msg.update_sess_info.called);
		buf[len++] = vallen;
		strcpy((char *)&buf[len], ptr->msg.update_sess_info.called);		
		len += vallen;
	}
	if((ptr->msg.update_sess_info.optional_flag & 0x02) == 0x02)
	{
		buf[len++] = IE_UE_IP;
		vallen = 0x04;
		buf[len++] = vallen;
		memcpy(&buf[len], &ptr->msg.update_sess_info.ue_ip, vallen);		
		len += vallen;
	}
	if((ptr->msg.update_sess_info.optional_flag & 0x04) == 0x04)
	{
		buf[len++] = IE_GW_IP;
		vallen = 0x04;
		buf[len++] = vallen;
		memcpy(&buf[len], &ptr->msg.update_sess_info.gw_ip, vallen);		
		len += vallen;
	}

	return len;

}

int encode_rest_update_plan_info(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;

	if(ptr == NULL || buf == NULL)
		return 0;
	
	ENCODE_HEADER();

	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.update_plan_info.msisdn);
	buf[len++] = vallen;
	strcpy((char *)&buf[len], ptr->msg.update_plan_info.msisdn);
	len += vallen;


	buf[len++] = IE_SERVICE_TYPE;
	vallen = 1;
	buf[len++] = vallen;
	buf[len]= ptr->msg.update_plan_info.service_type;	
	len += vallen;

	buf[len++] = IE_ACCOUNT_ID;
	vallen = 0x04;
	buf[len++] = vallen;
	*(u32*)(&buf[len]) = htonl(ptr->msg.update_plan_info.account_id);
	len += vallen;

	buf[len++] = IE_PLAN_ID;
	vallen = 0x04;
	buf[len++] = vallen;
	*(u32*)(&buf[len]) = htonl(ptr->msg.update_plan_info.plan_id);
	len += vallen;

	buf[len++] = IE_BUNDLE_ID;
	vallen = 0x04;
	buf[len++] = vallen;
	*(u32*)(&buf[len]) = htonl(ptr->msg.update_plan_info.bundle_id);
	len += vallen;

	buf[len++] = IE_PLAN_VALUE;
	vallen = 0x08;
	buf[len++] = vallen;
	_encode_u64(buf, &len, ptr->msg.update_plan_info.plan_total_value);

	buf[len++] = IE_PLAN_USED_VALUE;
	vallen = 0x08;
	buf[len++] = vallen;
	_encode_u64(buf, &len, ptr->msg.update_plan_info.plan_used_value);

	buf[len++] = IE_SESS_UPDATE_TIME;
	vallen = 0x04;
	buf[len++] = vallen;
	*(u32*)(&buf[len]) = htonl(ptr->msg.update_plan_info.sess_update_times);
	len += vallen;

	buf[len++] = IE_PLAN_VALUE_ADD_THIS_TIME;
	buf[len++] = 0x08;
	_encode_u64(buf, &len, ptr->msg.update_plan_info.this_time_add_value);
	
	return len;

}


int encode_rest_rent_charge(_rest_msg_s *ptr, u8 *buf)
{
	int len=0, vallen=0;

	if(ptr == NULL || buf == NULL)
		return 0;
	
	ENCODE_HEADER();

	buf[len++] = IE_MSISDN;
	vallen = strlen(ptr->msg.rent_charge.msisdn);
	buf[len++] = vallen;
	strcpy((char *)&buf[len], ptr->msg.rent_charge.msisdn);
	len += vallen;

	if((ptr->msg.update_subs.optional_flag & 0x01) == 0x01)
	{		
		buf[len++] = IE_BALANCE;
		buf[len++] = 0x04;
		*(u32*)(&buf[len]) = htonl(ptr->msg.rent_charge.balance);
		len += 0x04;
	
	}
	if((ptr->msg.update_subs.optional_flag & 0x02) == 0x02)
	{		
		buf[len++] = IE_RENT_CHARGE;
		buf[len++] = 0x04;
		*(u32*)(&buf[len]) = htonl(ptr->msg.rent_charge.rent_charge);
		len += 0x04;
	
	}
	
	return len;
}

int decode_rest_rent_charge(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			memcpy(ptr->msg.rent_charge.msisdn, &buf[offset], vallen);
			ptr->msg.rent_charge.msisdn[vallen] = '\0';
			break;
		case IE_BALANCE:
			ptr->msg.rent_charge.balance = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_RENT_CHARGE:
			ptr->msg.rent_charge.rent_charge = ntohl( *(u32*)(&buf[offset]) );
			break;			
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}
/*--------------------------------------------------------------------*/

static int decode_rest_send_authcode_req(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			memcpy(ptr->msg.send_authcode_req.msisdn, &buf[offset], vallen);
			ptr->msg.send_authcode_req.msisdn[vallen] = '\0';
			break;
		case IE_MSG_CONTENT:
			{
				int sms_len = vallen * 256 + buf[offset++];

				memcpy(ptr->msg.send_authcode_req.sms_content, &buf[offset], sms_len);
				ptr->msg.send_authcode_req.sms_content[sms_len] = '\0';
			}
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_query_user_data_req(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			memcpy(ptr->msg.query_user_data_req.msisdn, &buf[offset], vallen);
			ptr->msg.query_user_data_req.msisdn[vallen] = '\0';
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_bundle_subs_req(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			memcpy(ptr->msg.bundle_subs_req.msisdn, &buf[offset], vallen);
			ptr->msg.bundle_subs_req.msisdn[vallen] = '\0';
			break;
		case IE_PAY_TYPE: 
			ptr->msg.bundle_subs_req.payType = buf[offset];
			break;
		case IE_AMOUNT:
			ptr->msg.bundle_subs_req.charge = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_MO_VOICE_MIN:
			ptr->msg.bundle_subs_req.moVoiceMinute = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_MT_VOICE_MIN:
			ptr->msg.bundle_subs_req.mtVoiceMinute = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_DATA_VOL_MB:
			ptr->msg.bundle_subs_req.dataVolume = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_SMS_NUM:
			ptr->msg.bundle_subs_req.smsNum = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_VALID_DAYS:
			ptr->msg.bundle_subs_req.validDays = ntohl( *(u32*)(&buf[offset]) );
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_bundle_usage_req(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			memcpy(ptr->msg.bundle_usage_req.msisdn, &buf[offset], vallen);
			ptr->msg.bundle_usage_req.msisdn[vallen] = '\0';
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_recharge_req(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			memcpy(ptr->msg.recharge_req.msisdn, &buf[offset], vallen);
			ptr->msg.recharge_req.msisdn[vallen] = '\0';
			break;
		case IE_AMOUNT:
			ptr->msg.recharge_req.amount = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_RECHARGE_TYPE:
			ptr->msg.recharge_req.op_type = buf[offset];
			break;
		case IE_VALID_DAYS:
			ptr->msg.recharge_req.valid_days = ntohs( *(u16*)(&buf[offset]) );
			break;			
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_transfer_req(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN_TRANS_OUT:
			memcpy(ptr->msg.transfer_req.transferOutMsisdn, &buf[offset], vallen);
			ptr->msg.transfer_req.transferOutMsisdn[vallen] = '\0';
			break;
		case IE_MSISDN_TRANS_IN:
			{
				int num_len = vallen;
				if (num_len > 20)
				{
					num_len = 20;
				}
				memcpy(ptr->msg.transfer_req.transferInMsisdn, &buf[offset], num_len);
				ptr->msg.transfer_req.transferInMsisdn[num_len] = '\0';
			}
			break;
		case IE_AMOUNT:
			ptr->msg.transfer_req.amount = ntohl( *(u32*)(&buf[offset]) );
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_recharge_card_req(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			memcpy(ptr->msg.recharge_card_req.msisdn, &buf[offset], vallen);
			ptr->msg.recharge_card_req.msisdn[vallen] = '\0';
			break;
		case IE_PASSWORD:
			{
				int pwd_len = vallen;
				if (pwd_len > 20)
				{
					pwd_len = 20;
				}
				memcpy(ptr->msg.recharge_card_req.cardPwd, &buf[offset], pwd_len);
				ptr->msg.recharge_card_req.cardPwd[pwd_len] = '\0';
			}
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_check_balance_req(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			memcpy(ptr->msg.check_balance_req.msisdn, &buf[offset], vallen);
			ptr->msg.check_balance_req.msisdn[vallen] = '\0';
			break;
		case IE_AMOUNT:
			ptr->msg.check_balance_req.amount = ntohl( *(u32*)(&buf[offset]) );
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_query_balance_req(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			memcpy(ptr->msg.query_balance_req.msisdn, &buf[offset], vallen);
			ptr->msg.query_balance_req.msisdn[vallen] = '\0';
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}
//

static int decode_rest_query_balance_res(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_RESULT:
			ptr->msg.query_balance_rsp.result = buf[offset];
			break;
		case IE_ERROR_CODE:
			ptr->msg.query_balance_rsp.error_code = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_STATUS:
			ptr->msg.query_balance_rsp.status = buf[offset];
			break;
		case IE_BALANCE:
			ptr->msg.query_balance_rsp.balance = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_MO_EXPIRY:
			ptr->msg.query_balance_rsp.mo_expiry = ntohl( *(u32*)(&buf[offset]) );
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}
static int decode_rest_sms_deliver(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			memcpy(ptr->msg.sms_deliver.msisdn, &buf[offset], vallen);
			ptr->msg.sms_deliver.msisdn[vallen] = '\0';
			break;
		case IE_SMS_CONTENT:
			vallen = vallen * 256 + buf[offset++];			
			ptr->msg.sms_deliver.sms_len = vallen;
			memcpy(ptr->msg.sms_deliver.sms_content, &buf[offset], vallen);
			ptr->msg.sms_deliver.sms_content[vallen] = '\0';
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_sms_deliver_res(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_RESULT:
			ptr->msg.sms_deliver_res.result = buf[offset];
			break;
		case IE_ERROR_CODE:
			ptr->msg.sms_deliver_res.error_code = ntohl( *(u32*)(&buf[offset]) );
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_create_account(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			memcpy(ptr->msg.create_acct.msisdn, &buf[offset], vallen);
			ptr->msg.create_acct.msisdn[vallen] = '\0';
			break;
		case IE_CUSTOMER_ID:
			ptr->msg.create_acct.customer_id = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_ACCOUNT_ID:
			ptr->msg.create_acct.account_id = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_PRODUCT_ID:
			ptr->msg.create_acct.customer_id = ntohl( *(u32*)(&buf[offset]) );			
			break;
		case IE_PLAN_ID:
			ptr->msg.create_acct.plan_id = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_BALANCE:
			ptr->msg.create_acct.balance= ntohl( *(u32*)(&buf[offset]) );			
			break;
		case IE_EXPIRY_TIME:
			ptr->msg.create_acct.expiry_date = ntohl( *(u32*)(&buf[offset]) );			
			break;
		case IE_RENT_CHARGE:
			ptr->msg.create_acct.rent_charge = ntohl( *(u32*)(&buf[offset]) );
			break;			
		case IE_BIRTHDAY:
			ptr->msg.create_acct.birthday = ntohl( *(u32*)(&buf[offset]) );			
			break;
		case IE_CUG_ID:
			ptr->msg.create_acct.cug_id = ntohl( *(u32*)(&buf[offset]) );			
			break;
		case IE_USER_CLASS:
			ptr->msg.create_acct.user_class = buf[offset];			
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_create_account_res(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_RESULT:
			ptr->msg.create_acct_res.result = buf[offset];
			break;
		case IE_ERROR_CODE:
			ptr->msg.create_acct_res.error_code = ntohl( *(u32*)(&buf[offset]) );
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_query_tariff(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_SERVICE_TYPE:
			ptr->msg.query_tariff.service_type = buf[offset];
			break;
		case IE_MSISDN:
			strcpy(ptr->msg.query_tariff.msisdn, (char *)&buf[offset]);
			ptr->msg.query_tariff.msisdn[vallen] = 0;
			break;
		case IE_TARIIFF_PREFIX:
			strcpy(ptr->msg.query_tariff.called_number, (char *)&buf[offset]);
			ptr->msg.query_tariff.called_number[vallen] = 0;
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_query_tariff_res(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_RESULT:
			ptr->msg.query_tariff_res.result = buf[offset];
			break;
		case IE_ERROR_CODE:
			ptr->msg.query_tariff_res.error_code = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_TARIIFF_PREFIX:
			strcpy(ptr->msg.query_tariff_res.prefix, (char *)&buf[offset]);
			break;
		case IE_TARIFF_UNIT:
			ptr->msg.query_tariff_res.unit_time = ntohl( *(u32*)(&buf[offset]) );			
			break;
		case IE_TARIFF_CHARGE:
			ptr->msg.query_tariff_res.unit_charge = ntohl( *(u32*)(&buf[offset]) );			
			break;
		case IE_TARIFF_DISCOUNT:
			ptr->msg.query_tariff_res.discount = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_PLAN_ID:
			ptr->msg.query_tariff_res.plan_id = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_PLAN_VALUE:
			ptr->msg.query_tariff_res.total_plan_value = _decode_u64( &buf[offset] );						
			break;
		case IE_PLAN_USED_VALUE:
			ptr->msg.query_tariff_res.used_plan_value = _decode_u64( &buf[offset] );			
			break;
		case IE_BUNDLE_ID:
			ptr->msg.query_tariff_res.bundle_plan_id = ntohl( *(u32*)(&buf[offset]) );
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_update_subs(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	ptr->msg.update_subs.optional_flag = 0x00;
	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			strcpy(ptr->msg.update_subs.msisdn, (char *)&buf[offset]);
			ptr->msg.update_subs.msisdn[vallen] = 0;
			break;
		case IE_ACCOUNT_ID:
			ptr->msg.update_subs.account_id = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_STATUS:
			ptr->msg.update_subs.status = buf[offset];
			ptr->msg.update_subs.optional_flag |= 0x01;
			break;
		case IE_BALANCE:
			ptr->msg.update_subs.balance = ntohl( *(u32*)(&buf[offset]) );			
			ptr->msg.update_subs.optional_flag |= 0x02;
			break;		
		case IE_EXPIRY_TIME:
			ptr->msg.update_subs.balance_expiry_date = ntohl( *(u32*)(&buf[offset]) );
			ptr->msg.update_subs.optional_flag |= 0x04;			
			break;	
		case IE_PLAN_ID:
			ptr->msg.update_subs.basic_plan_id = ntohl( *(u32*)(&buf[offset]) );
			ptr->msg.update_subs.optional_flag |= 0x08;
			break;
		case IE_RENT_CHARGE:
			ptr->msg.update_subs.basic_plan_rent = ntohl( *(u32*)(&buf[offset]) );
			ptr->msg.update_subs.optional_flag |= 0x10;
			break;
		case IE_VAS_CUG_STATUS:
			ptr->msg.update_subs.vas_cug_status = buf[offset];
			ptr->msg.update_subs.optional_flag |= 0x20;			
			break;			
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_update_subs_res(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_RESULT:
			ptr->msg.update_subs_res.result = buf[offset];
			break;
		case IE_ERROR_CODE:
			ptr->msg.update_subs_res.error_code = ntohl( *(u32*)(&buf[offset]) );
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}
static int decode_rest_delete_subs(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			strcpy(ptr->msg.delete_subs.msisdn, (char *)&buf[offset]);
			ptr->msg.delete_subs.msisdn[vallen] = 0;
			break;
		case IE_CAUSE:
			ptr->msg.delete_subs.cause = buf[offset];
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_delete_subs_res(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_RESULT:
			ptr->msg.delete_subs_res.result = buf[offset];
			break;
		case IE_ERROR_CODE:
			ptr->msg.delete_subs_res.error_code = ntohl( *(u32*)(&buf[offset]) );
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}


static int decode_rest_update_sess_info(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			strcpy(ptr->msg.update_sess_info.msisdn, (char *)&buf[offset]);
			ptr->msg.update_sess_info.msisdn[vallen] = 0;
			break;
		case IE_SESS_FLAG:
			ptr->msg.update_sess_info.first_sess = buf[offset];
			break;
		case IE_SERVICE_TYPE:
			ptr->msg.update_sess_info.first_sess = buf[offset];
			break;
		case IE_TIMESTAMP:
			ptr->msg.update_sess_info.start_time = ntohl( *(u32*)(&buf[offset]) );			
			break;
		case IE_CONSUME_VALUE:
			ptr->msg.update_sess_info.consumed_value = ntohl( *(u32*)(&buf[offset]) );			
			break;
		case IE_CALLED_NUMBER:
			strcpy(ptr->msg.update_sess_info.called, (char *)&buf[offset]);
			ptr->msg.update_sess_info.called[vallen] = 0;
			ptr->msg.update_sess_info.optional_flag |= 0x01;
			break;			
		case IE_UE_IP:
			memcpy(&ptr->msg.update_sess_info.ue_ip, &buf[offset], 4);
			ptr->msg.update_sess_info.optional_flag |= 0x02;			
			break;
		case IE_GW_IP:
			memcpy(&ptr->msg.update_sess_info.gw_ip, &buf[offset], 4);
			ptr->msg.update_sess_info.optional_flag |= 0x04;			
			break;
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

static int decode_rest_update_plan_info(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;
	int tag = 0, vallen=0;

	while(offset<len)
	{
		tag = buf[offset++];
		vallen = buf[offset++];
		switch (tag)
		{
		case IE_SRC_REF:
			ptr->header.src_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_DST_REF:
			ptr->header.dst_ref = ntohs( *(u16*)(&buf[offset]) );
			break;
		case IE_MSISDN:
			strcpy(ptr->msg.update_plan_info.msisdn, (char *)&buf[offset]);
			ptr->msg.update_plan_info.msisdn[vallen] = 0;
			break;
		case IE_SERVICE_TYPE:
			ptr->msg.update_plan_info.service_type = buf[offset];
			break;
		case IE_ACCOUNT_ID:
			ptr->msg.update_plan_info.account_id = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_PLAN_ID:
			ptr->msg.update_plan_info.plan_id = ntohl( *(u32*)(&buf[offset]) );			
			break;
		case IE_BUNDLE_ID:
			ptr->msg.update_plan_info.bundle_id = ntohl( *(u32*)(&buf[offset]) );
			break;
		case IE_PLAN_VALUE:
			ptr->msg.update_plan_info.plan_total_value = _decode_u64(&buf[offset] );			
			break;
		case IE_PLAN_USED_VALUE:
			ptr->msg.update_plan_info.plan_used_value =  _decode_u64( &buf[offset] );				
			break;
		case IE_SESS_UPDATE_TIME:
			ptr->msg.update_plan_info.sess_update_times = ntohl( *(u32*)(&buf[offset]) );			
			break;
		case IE_PLAN_VALUE_ADD_THIS_TIME:
			ptr->msg.update_plan_info.this_time_add_value = _decode_u64(&buf[offset]);			
			break;			
		default:
			break;
		}
		offset += vallen;
	}
	
	return retval;
}

/* --------------------------------------------------------*/
int decode_rest_api_msg(u8 *buf, int len, _rest_msg_s *ptr)
{
	int retval = 1;
	int offset = 0;

	if (len <= 9)
	{
		return -1;
	}

	ptr->msg_type = buf[offset++];

	switch (ptr->msg_type)
	{
	case REST_QUERY:
		decode_rest_query(buf+1, len-1, ptr);
		break;
	case REST_TOPUP:
		decode_rest_topup(buf+1, len-1, ptr);
		break;
	case REST_TRANSFER:
		decode_rest_transfer_res(buf+1, len-1, ptr);
		break;
	case REST_CHANNEL:
		decode_rest_channel_res(buf+1, len-1, ptr);
		break;
	case REST_POINT_QUERY:
		decode_rest_queryPoint_res(buf+1, len-1, ptr);
		break;
	case REST_POINT_TRANSFER:
		decode_rest_transferPoint_res(buf+1, len-1, ptr);
		break;
	// for selfcare
	case REST_SEND_AUTHCODE_REQ:
		decode_rest_send_authcode_req(buf+1, len-1, ptr);
		break;
	case REST_QUERY_USERDATA_REQ:
		decode_rest_query_user_data_req(buf+1, len-1, ptr);
		break;
	case REST_BUNDLE_SUBS_REQ:
		decode_rest_bundle_subs_req(buf+1, len-1, ptr);
		break;
	case REST_BUNDLE_USAGE_REQ:
		decode_rest_bundle_usage_req(buf+1, len-1, ptr);
		break;
	case REST_RECHARGE_REQ:
		decode_rest_recharge_req(buf+1, len-1, ptr);
		break;
	case REST_TRANSFER_REQ:
		decode_rest_transfer_req(buf+1, len-1, ptr);
		break;
	case REST_RECHARGE_CARD_REQ:
		decode_rest_recharge_card_req(buf+1, len-1, ptr);
		break;
	case REST_CHECK_BALANCE_REQ:
		decode_rest_check_balance_req(buf+1, len-1, ptr);
		break;
	case REST_QUERY_BALANCE_REQ:
		decode_rest_query_balance_req(buf+1, len-1, ptr);
		break;
	case REST_CRM_SMS_DELIVER_REQ:
		decode_rest_sms_deliver(buf+1, len-1, ptr);
		break;
	case REST_CRM_SMS_DELIVER_RES:
		decode_rest_sms_deliver_res(buf+1, len-1, ptr);		
		break;
	case REST_CRM_CREATE_ACCT_REQ:
		decode_rest_create_account(buf+1, len-1, ptr);
		break;
	case REST_CRM_CREATE_ACCT_RES:
		decode_rest_create_account_res(buf+1, len-1, ptr);	
		break;
	case REST_CRM_QUERY_TARIFF_RES:
		decode_rest_query_tariff_res(buf+1, len-1, ptr);			
		break;
	case REST_CRM_UPDATE_SUBS_REQ:
		decode_rest_update_subs(buf+1, len-1, ptr);
		break;
	case REST_CRM_DELETE_SUBS_REQ:
		decode_rest_delete_subs(buf+1, len-1, ptr);
		break;
	case REST_CRM_UPDATE_SESS_INFO_REQ:
		decode_rest_update_sess_info(buf+1, len-1, ptr);
		break;
	case REST_CRM_UPDATE_PLAN_INFO_REQ:
		decode_rest_update_plan_info(buf+1, len-1, ptr);		
		break;
	default:
		break;
	}
	
	return retval;
}

