/*
*********************************************************************************
*                                                                               *
* NOTICE:                                                                 *
*                                                                               *
*********************************************************************************
*                        mgcChnl <-----------mgcConnections
*/
 
    
/*********************************************************************************
 *                              <mgc_connect_info.c>                                                              
 *     This file should provide CONNECT_INFO object APIs used in MGC module. Every CONNECT_INFO
 * object should be attached to CHNL_INFO object
 *
 *    Author                         Date
 *    ------                        ------
 *    Sam Yao                     Aug 2008                                                                                              
 *********************************************************************************/



/*-----------------------------------------------------------------------*/
/*                        INCLUDE HEADER FILES                           */
/*-----------------------------------------------------------------------*/

#include "./include/mgc_conn_info.h"
#include "./include/mgc_debug.h"
#include "./include/mgc_mgcp.h"
#include "./include/mgc_mg_info.h"
#include "./include/mgc_chnl_info.h"
#include "./include/mgc_tandem_info.h"
#include "./include/mgc_port_info.h"
/*-----------------------------------------------------------------------*/
/*                       GLOABLE definition                           */
/*-----------------------------------------------------------------------*/

#define MGC_PKG_SIG_G_RT			((MGCP_PKG_G << 8) | MGCP_G_SIG_RT)
#define MGC_PKG_SIG_L_BZ			((MGCP_PKG_L << 8) | MGCP_L_SIG_BZ)
#define MGC_PKG_SIG_L_WT			((MGCP_PKG_L << 8) | MGCP_L_SIG_WT)


const WORD 	MGC_TONE_NO_TO_PKG_SIG[16] =
{
	MGC_PKG_SIG_L_BZ, MGC_PKG_SIG_L_BZ, MGC_PKG_SIG_L_BZ, MGC_PKG_SIG_L_BZ,
	MGC_PKG_SIG_L_BZ, MGC_PKG_SIG_L_BZ, MGC_PKG_SIG_L_BZ, MGC_PKG_SIG_L_BZ,
	MGC_PKG_SIG_G_RT, MGC_PKG_SIG_L_BZ, MGC_PKG_SIG_L_BZ, MGC_PKG_SIG_L_WT,
	MGC_PKG_SIG_L_BZ, MGC_PKG_SIG_L_BZ, MGC_PKG_SIG_L_BZ, MGC_PKG_SIG_L_BZ
};


static CONNECT_INFO  mgcConnectInfo[MGC_MAX_NUM_OF_CON];

/*-----------------------------------------------------------------------
              CONNCET_INFO      M A N A G E R
 ------------------------------------------------------------------------*/	 

char *mgc_connect_print_statuts(MGC_CONNECT_STATUS status)
{
    switch(status)
    {
        case MGC_CONNECT_STATUS_UNDEF:
			return "MGC_CONNECT_STATUS_UNDEF";
		case MGC_CONNECT_STATUS_IDLE:
			return "MGC_CONNECT_STATUS_IDLE";
		case MGC_CONNECT_STATUS_CREATING:
			return "MGC_CONNECT_STATUS_CREATING";
		case MGC_CONNECT_STATUS_CREATED:
			return "MGC_CONNECT_STATUS_CREATED";
		case MGC_CONNECT_STATUS_CREATE:
			return "MGC_CONNECT_STATUS_CREATE";
    }
	return "MGC_CONNECT_STATUS_UNKNOW";
}


void mgc_connect_codec_list_init(MGC_CODEC_LIST  *pList)
{
    int i;

    if(pList == NULL)
	    return ;

	for(i=0 ; i<MGC_VCTYPE_NUM ; i++)
	    pList->codec[i] = MGC_VCTYPE_UNSUPPORT;

	pList->num = 0;
	pList->priority = 0;
	return;
}

/***************************************************************************
 * mgc_connect_init
 * ------------------------------------------------------------------------
 * General: init CONNCET_INFO structure objcet
 * Return Value:  void.
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnect- the pointer of the CONNCET_INFO object which should be init
 *	       id - the id of the CHNL_INFO object
 ***************************************************************************/
void mgc_connect_init(CONNECT_INFO *pConnect , int id)
{
    if((pConnect == NULL) || (id < 0))
        return;

    pConnect->id = id;
	pConnect->flag = 0;
	pConnect->status = MGC_CHNL_INFO_STATUS_UNDEF;
	pConnect->pChnlInfo = NULL;
	pConnect->pOperStep= NULL;	
#ifdef MGC_REC_PORT
    pConnect->pPrePortInfo= NULL;
#endif	
	pConnect->pTandem = NULL;
	mgc_connect_codec_list_init(&pConnect->codecList);
	memset(&pConnect->mediaAttr , 0 , sizeof(MEDIA_ATTR));
	memset(&pConnect->operRec , 0 , sizeof(OPER_REC));
	memset(&pConnect->mgcpRec , 0 , sizeof(MGCP_REC_TAG));
	return;
}

void mgc_connect_setup(void)
{
    int i;
	CONNECT_INFO *pConnect = NULL;
	
    for(i=0 ; i<MGC_MAX_NUM_OF_CON ; i++)	
    {
        pConnect = &mgcConnectInfo[i];
		mgc_connect_init(pConnect, i);
    }
    return;
}

/***************************************************************************
 * mgc_connect_get_unused
 * ------------------------------------------------------------------------
 * General: get CONNCET_INFO structure objcet
 * Return Value:  if failure return NULL , else return the object pointer
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: void
 ***************************************************************************/
CONNECT_INFO *mgc_connect_get_unused(void)
{
    int i;
	static int index = 0;
	CONNECT_INFO *pConnect = NULL;
	CONNECT_INFO *pConnectTmp = NULL;

    i = index;
    do
    {
        i++;

        if(i == MGC_MAX_NUM_OF_CON)	
		    i=0;
		
        pConnect = &mgcConnectInfo[i];

		if(pConnect->pChnlInfo != NULL)
		    continue;	

        if(pConnect->pOperStep!= NULL)
            continue;
		
        pConnectTmp = pConnect;
		index = i;
		break;

    }while(i != index);

    return pConnectTmp;
}

int mgc_connect_unused_num(void)
{
    int i , num;
	CONNECT_INFO *pConnect = NULL;

    num = 0;
    for(i=0 ; i<MGC_MAX_NUM_OF_CON ; i++)
    {
        pConnect = &mgcConnectInfo[i];

		if(pConnect->pChnlInfo != NULL)
		    continue;	

		num++;
    }

    return num;	
}

/***************************************************************************
 * mgc_connect_attach_step_info
 * ------------------------------------------------------------------------
 * General: record the operate step which will do sth on this CONNCET_INFO object
 * Return Value:  if failure return FALSE , else return TRUE.
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnect - the pointer of the CONNCET_INFO object which will be used 
 *	       pOperStep - the pointer of the step which will operate on the conncet
 ***************************************************************************/
BOOL mgc_connect_attach_step_info(CONNECT_INFO *pConnect , MGCF_OPER_STEP *pOperStep)
{
    if((pConnect == NULL)||(pOperStep == NULL))
        return FALSE;

    if(pConnect->pOperStep != NULL)
	    return FALSE;
	
    pConnect->pOperStep = pOperStep;
	return TRUE;
}

BOOL mgc_connect_dettach_step_info(CONNECT_INFO *pConnect)
{
    if(pConnect == NULL)
        return FALSE;

    pConnect->pOperStep = NULL;
	return TRUE;
}

/***************************************************************************
 * mgc_connect_get_step_info
 * ------------------------------------------------------------------------
 * General: get the step info related to this conncetion
 * Return Value:  if failure return NULL , else return the pointer of the operate step.
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnect - the pointer of the CONNCET_INFO object
 ***************************************************************************/
MGCF_OPER_STEP *mgc_connect_get_step_info(CONNECT_INFO *pConnect)
{
    if(pConnect == NULL)
	    return NULL;	

	return pConnect->pOperStep;
}

/***************************************************************************
 * mgc_connect_find_connect_of_chnl
 * ------------------------------------------------------------------------
 * General: get the CONNCET_INFO object in the CHNL_INFO object
 * Return Value:  if failure return NULL , else return the pointer of the CONNCET_INFO object.
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pChnlInfo - the pointer of the CHNL_INFO object which contain the CONNCET_INFO ojbects
 *           connNo - the place where record CONNECT_INFO object 
 ***************************************************************************/
CONNECT_INFO *mgc_connect_find_connect_of_chnl(CHNL_INFO *pChnlInfo , int connNo)
{
    CONNECT_INFO *pConnect = NULL;
	
    if(pChnlInfo == NULL)
       return NULL;		

   if((connNo < 0)||(connNo > MGC_MAX_NUM_OF_CHNL_CON))
   	   return NULL;

    pConnect = pChnlInfo->pConnection[connNo];
    if(pConnect == NULL)
        return NULL;

    return pConnect;
}

/***************************************************************************
 * mgc_connect_attach_connect_to_chnl
 * ------------------------------------------------------------------------
 * General: record the owner of the CONNCET_INFO object
 * Return Value:  if failure return FALSE , else return TRUE.
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 *           pChnlInfo - the pointer of the CHNL_INFO object which contain the CONNCET_INFO object
 ***************************************************************************/
BOOL mgc_connect_attach_connect_to_chnl(CONNECT_INFO *pConnect , CHNL_INFO *pChnlInfo)
{
    if((pConnect == NULL)||(pChnlInfo == NULL))
        return FALSE;

    if(pConnect->pChnlInfo != NULL)	
        return FALSE;		

    pConnect->pChnlInfo = pChnlInfo;
	return TRUE;
}

/***************************************************************************
 * mgc_connect_set_status
 * ------------------------------------------------------------------------
 * General:  set the status of the CONNCET_INFO object
 * Return Value:  void.
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 *           status - the status of the CONNCET_INFO objecct
 ***************************************************************************/
void mgc_connect_set_status(CONNECT_INFO *pConnect , MGC_CONNECT_STATUS status)
{
    if(pConnect == NULL)
        return;

    if((pConnect->status != status)&&(pConnect->status != MGC_CONNECT_STATUS_UNDEF))
    {
        MGC_DEBUG("conn[%d] state %s =>> %s" ,
		pConnect->id , mgc_connect_print_statuts(pConnect->status) , mgc_connect_print_statuts(status));
    }
    pConnect->status = status;
}

/***************************************************************************
 * mgc_connect_get_status
 * ------------------------------------------------------------------------
 * General:  get the status of the CONNCET_INFO object
 * Return Value:  return the status of the CONNCET_INFO object
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 ***************************************************************************/
MGC_CONNECT_STATUS mgc_connect_get_status(CONNECT_INFO *pConnect)
{
    if(pConnect == NULL)
        return MGC_CONNECT_STATUS_UNDEF;

	return pConnect->status;
}

/***************************************************************************
 * mgc_connect_set_dtmf
 * ------------------------------------------------------------------------
 * General:  set the dtmf info in the conncet
 * Return Value:  if failure return FALSE , else return TRUE
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 *            dtmfNo - the dtmf 
 ***************************************************************************/
BOOL mgc_connect_set_dtmf(CONNECT_INFO *pConnect , BYTE dtmfNo)
{
    BYTE digit;
	MEDIA_ATTR *pMedia = NULL;
	
    if(pConnect == NULL)
        return FALSE;		

    digit = dtmfNo;
    if(digit == 0)	
	    digit = 10;

    pMedia = &pConnect->mediaAttr;
	pMedia->pkgSignal.pkg = MGCP_PKG_D;
	pMedia->pkgSignal.signal = digit;
    return TRUE;	
}

/***************************************************************************
 * mgc_connect_clear_tone
 * ------------------------------------------------------------------------
 * General:  clear tone info in the CONNCET_INFO object
 * Return Value:  if failure return FALSE, else return TRUE
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 ***************************************************************************/
BOOL mgc_connect_clear_tone(CONNECT_INFO *pConnect)
{
	MEDIA_ATTR *pMedia = NULL;
    if(pConnect == NULL)
        return FALSE;		

    pMedia = &pConnect->mediaAttr;
	pMedia->pkgSignal.pkg = 0;
	pMedia->pkgSignal.signal = 0;
    return TRUE;	
}

/***************************************************************************
 * mgc_connect_set_tone
 * ------------------------------------------------------------------------
 * General: set tone info in the CONNCET_INFO object
 * Return Value:  if failure return FALSE, else return TRUE
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 *            toneNo - tone id
 ***************************************************************************/
BOOL mgc_connect_set_tone(CONNECT_INFO *pConnect , BYTE toneNo)
{
	MEDIA_ATTR *pMedia = NULL;
	WORD pkgSignal;
    if(pConnect == NULL)
        return FALSE;		

    pkgSignal = MGC_TONE_NO_TO_PKG_SIG[toneNo];
    pMedia = &pConnect->mediaAttr;
	pMedia->pkgSignal.pkg = (pkgSignal&0xFF00) >> 8;
	pMedia->pkgSignal.signal = (pkgSignal&0x00FF);
	MGC_DEBUG("conn[%d] set pkg[%d]sig[%d]" , pConnect->id , pMedia->pkgSignal.pkg , pMedia->pkgSignal.signal);
    return TRUE;	
}

/***************************************************************************
 * mgc_connect_set_tone
 * ------------------------------------------------------------------------
 * General:  set request on the specific connect
 * Return Value:  if failure return FALSE, else return TRUE
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 *            pkg - the name of the package
 *            req - the name of the request
 ***************************************************************************/
BOOL mgc_connect_set_req(CONNECT_INFO *pConnect , BYTE pkg , BYTE req)
{
	MEDIA_ATTR *pMedia = NULL;

    if(pConnect == NULL)
        return FALSE;		

    pMedia = &pConnect->mediaAttr;
	pMedia->pkgReq.pkg = pkg;
	pMedia->pkgReq.req = req;
	MGC_DEBUG("conn[%d] set pkg[%d]req[%d]" , pConnect->id , pMedia->pkgReq.pkg , pMedia->pkgReq.req);
    return TRUE;	
}



/***************************************************************************
 * mgc_connect_get_own_chnl_info
 * ------------------------------------------------------------------------
 * General:  get the owner CHNL_INFO object of the CONNCET_INFO object
 * Return Value:  if failure return NULL , else return the pointer of the CHNL_INFO object
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 ***************************************************************************/
CHNL_INFO  *mgc_connect_get_own_chnl_info(CONNECT_INFO *pConnect)
{
    CHNL_INFO *pChnlInfo = NULL;

    if(pConnect == NULL)
        return NULL;		

    pChnlInfo = pConnect->pChnlInfo;
    if(pChnlInfo == NULL)
        return NULL;

    return pChnlInfo;
}



/***************************************************************************
 * mgc_connect_get_own_phy_port_info
 * ------------------------------------------------------------------------
 * General:  get the owner phyPort  of the CONNCET_INFO object
 * Return Value:  if failure return NULL , else return the pointer of the PHY_PORT_INFO object
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 ***************************************************************************/
PHY_PORT_INFO  *mgc_connect_get_own_phy_port_info(CONNECT_INFO *pConnect)
{
    CHNL_INFO *pChnlInfo = NULL;
	PHY_PORT_INFO *pPhyPort = NULL;

    if(pConnect == NULL)
        return NULL;		

    pChnlInfo = pConnect->pChnlInfo;
    if(pChnlInfo == NULL)
        return NULL;
	
    pPhyPort = pChnlInfo->pPhyPort;
    if(pPhyPort == NULL)
        return NULL;		
    
    return pPhyPort;
}


/***************************************************************************
 * mgc_connect_get_conn_report_sap
 * ------------------------------------------------------------------------
 * General:  get the MGC_SAP info from the CONNCET_INFO object
 * Return Value:  if failure return NULL , else return the pointer of the MGC_SAP object
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 ***************************************************************************/
MGC_SAP *mgc_connect_get_conn_report_sap(CONNECT_INFO *pConnect)
{
	PHY_PORT_INFO *pPhyPort = NULL;

    pPhyPort = mgc_connect_get_own_phy_port_info(pConnect);
	if(pPhyPort == NULL)
	    return NULL;

	return pPhyPort->pMgcSap;
}

/***************************************************************************
 * mgc_connect_get_own_mg_info
 * ------------------------------------------------------------------------
 * General:  get the owner MG_INFO object  of the CONNCET_INFO object
 * Return Value:  if failure return NULL , else return the pointer of the MG_INFO object
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 ***************************************************************************/
MG_INFO *mgc_connect_get_own_mg_info(CONNECT_INFO *pConnect)
{
    CHNL_INFO *pChnlInfo = NULL;
	PHY_PORT_INFO *pPhyPort = NULL;
    MG_INFO *pMgInfo = NULL;

    if(pConnect == NULL)
        return NULL;		

    pChnlInfo = pConnect->pChnlInfo;
    if(pChnlInfo == NULL)
        return NULL;
	
    pPhyPort = pChnlInfo->pPhyPort;
    if(pPhyPort == NULL)
        return NULL;		

    pMgInfo = pPhyPort->pMgInfo;
	if(pMgInfo == NULL)
        return NULL;	

	return pMgInfo;
}


/***************************************************************************
 * mgc_connect_get_connNo_of_chnl_info
 * ------------------------------------------------------------------------
 * General:  get the record place of the CONNCET_INFO in it's owner CHNL_INFO
 * Return Value:  if failure return -1 , else return place number
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 *           pChnlInfo -  the pointer of the CHNL_INFO object
 ***************************************************************************/
int mgc_connect_get_connNo_of_chnl_info(CONNECT_INFO *pConnect , CHNL_INFO *pChnlInfo)
{
    int i;

    if((pConnect == NULL)||(pChnlInfo == NULL))
        return -1;

    for(i=0 ; i<MGC_MAX_NUM_OF_CHNL_CON ; i++)
    {
        if(pChnlInfo->pConnection[i] == NULL)
		    continue;	

		if(pChnlInfo->pConnection[i] != pConnect)
		    continue;

		return i;
    }

	return -1;
}


/***************************************************************************
 * mgc_connect_attr_init
 * ------------------------------------------------------------------------
 * General:  init the attribute of the connect
 * Return Value:  void
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 ***************************************************************************/
void mgc_connect_attr_init(CONNECT_INFO *pConnect)
{
    MG_INFO *pMgInfo = NULL;
    MG_INFO *pTarMgInfo = NULL;	
	MG_ATTR *pMgAttr = NULL;
	MEDIA_ATTR *pMediaAttr = NULL;
	MGCF_STEP_INFO *pStepInfo = NULL;
	MGC_CODEC_LIST *pCodecList = NULL;

    if((pConnect == NULL)||(pConnect->pOperStep == NULL))
        return;		

    pMediaAttr = &pConnect->mediaAttr;
    pStepInfo = &pConnect->pOperStep->stepInfo;
    pMgInfo = mgc_connect_get_own_mg_info(pConnect);
	if(pMgInfo == NULL)
        return;

    pMgAttr = &pMgInfo->mgAttr;
	pCodecList = &pStepInfo->codecList;
    mgc_connect_set_conn_mode(pConnect, pStepInfo->mode);

    if(pConnect->codecList.num == 0)
    {
        mgc_mgcp_match_codec_list(&pConnect->codecList, &pConnect->codecList, &pMgAttr->codecList);
	}

    if(pMediaAttr->ptime == 0)
	pMediaAttr->ptime = pMgInfo->mgAttr.ptime;
	
    if((mgc_tandem_info_get_conn_pos(pConnect->pTandem, pConnect) == MGC_TANDEM_CONN_POS_TX)
	   ||(mgc_tandem_info_get_conn_pos(pConnect->pTandem, pConnect) == MGC_TANDEM_CONN_POS_RX))
    {
		pTarMgInfo = mgc_connect_get_own_mg_info(pConnect->pTandem->pTconn);
	
        if(pConnect->pTandem->pTconn == NULL)
        {
            MGC_ERROR("tandem[%d] lost TarConn", pConnect->pTandem->id);
        }
		else if(mgc_connect_get_status(pConnect->pTandem->pTconn) == MGC_CONNECT_STATUS_CREATED)
		{
		    memcpy(&pConnect->codecList , &pConnect->pTandem->pTconn->codecList , sizeof(MGC_CODEC_LIST));
			pMediaAttr->ptime = pConnect->mediaAttr.ptime;
		}
		else
		{
			if(pTarMgInfo != NULL)		        
			{
                memcpy(&pConnect->codecList , &pTarMgInfo->mgAttr.codecList , sizeof(MGC_CODEC_LIST));
		             pMediaAttr->ptime = pTarMgInfo->mgAttr.ptime;
			}
		}

    }

    if(pCodecList->num != 0)
    {    
        memcpy(&pConnect->codecList , pCodecList , sizeof(MGC_CODEC_LIST));
    }
	
	pMediaAttr->vocoderType = pConnect->codecList.codec[0];

    if(mgc_tandem_info_get_conn_pos(pConnect->pTandem, pConnect) != MGC_TANDEM_CONN_POS_SUR)
        sprintf(pMediaAttr->callId , "%x%lx" , pConnect->id ,time(NULL));   	    
    
    return;    	
}


/***************************************************************************
 * mgc_connect_attr_negotiate
 * ------------------------------------------------------------------------
 * General:  do media info negotiate, this function should be used only when conncet related step
                  opera is set.
 * Return Value:  if failure return FALSE , else return TRUE
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 ***************************************************************************/
BOOL mgc_connect_attr_negotiate(CONNECT_INFO *pConnect)
{
    MGC_CODEC_LIST codecList;
	CONNECT_INFO *pConnectTmp = NULL;
	MGCF_STEP_INFO *pStepInfo = NULL;
	int ret = -1;
	
    if((pConnect == NULL)||(pConnect->pOperStep== NULL))
        return FALSE;

    pStepInfo = &(pConnect->pOperStep->stepInfo);
    pConnectTmp = pStepInfo->pPeerConn;
    mgc_connect_codec_list_init(&codecList);
    MGC_DEBUG("enter %s " , __FUNCTION__);
    if(pConnectTmp == NULL)
    {
        MGC_ERROR("conn[%d] lost peer connection info" , pConnectTmp->id);
        return FALSE;
    }

    if(mgc_tandem_info_get_conn_pos(pConnect->pTandem, pConnect) == MGC_TANDEM_CONN_POS_TAR)
    {
        if(mgc_tandem_info_get_conn_pos(pConnectTmp->pTandem, pConnectTmp) != MGC_TANDEM_CONN_POS_TX)
        {
            MGC_ERROR("conn[%d] is not a TxConn in Tandem" , pConnectTmp->id);
			return FALSE;
        }

		if(pConnect->pTandem->pAconn != NULL)
		{
            pConnectTmp = pConnect->pTandem->pAconn;
		}
    }
    else if(mgc_tandem_info_get_conn_pos(pConnect->pTandem, pConnect) == MGC_TANDEM_CONN_POS_AOR)
    {
        if(mgc_tandem_info_get_conn_pos(pConnectTmp->pTandem, pConnectTmp) != MGC_TANDEM_CONN_POS_RX)
        {
            MGC_ERROR("conn[%d] is not a RxConn in Tandem" , pConnectTmp->id);
			return FALSE;
        }         

		if(pConnect->pTandem->pTconn != NULL)
		{
            pConnectTmp = pConnect->pTandem->pTconn;
		}		
    }
    else if(mgc_tandem_info_get_conn_pos(pConnect->pTandem, pConnect) == MGC_TANDEM_CONN_POS_TX)
    {
		if(pConnect->pTandem->pTconn != NULL)
		{
			pConnectTmp = pConnect->pTandem->pTconn;
			memcpy(&pConnect->codecList , &pConnectTmp->codecList , sizeof(MGC_CODEC_LIST));
		}
    }
	else if(mgc_tandem_info_get_conn_pos(pConnect->pTandem, pConnect) == MGC_TANDEM_CONN_POS_RX)
	{

		if(pConnect->pTandem->pAconn!= NULL)
		{
             pConnectTmp = pConnect->pTandem->pAconn;
		     memcpy(&pConnect->codecList , &pConnectTmp->codecList , sizeof(MGC_CODEC_LIST));					 
		}
		
	}
    else if(mgc_tandem_info_get_conn_pos(pConnect->pTandem, pConnect) == MGC_TANDEM_CONN_POS_SUR)
    {
        if(strcmp(pConnect->mediaAttr.callId , pConnect->pTandem->pTxconn->mediaAttr.callId) == 0)
        {
            memcpy(&pConnect->codecList , &pConnect->pTandem->pTxconn->codecList , sizeof(MGC_CODEC_LIST));
        }
		else if(strcmp(pConnect->mediaAttr.callId , pConnect->pTandem->pRxconn->mediaAttr.callId) == 0)
		{
            memcpy(&pConnect->codecList , &pConnect->pTandem->pRxconn->codecList , sizeof(MGC_CODEC_LIST));
		}
		else
		{
		    MGC_ERROR("SurConn[%d] is illegal!" , pConnect->id);
			return FALSE;
		}
    }

    if(pConnectTmp != NULL)
    {
        if(pConnect->mediaAttr.ptime > pConnectTmp->mediaAttr.ptime)
        {
            pConnect->mediaAttr.ptime = pConnect->mediaAttr.ptime;
        }
	    else
	    {
	        pConnect->mediaAttr.ptime = pConnectTmp->mediaAttr.ptime;
	    }	    
    }

    if(pConnect->mediaAttr.ptime == 0)
    {
        MGC_WARN("ptime negotiate failed!");
		pConnect->mediaAttr.ptime = 20;
    }

    pConnectTmp = pStepInfo->pPeerConn;
	ret = mgc_mgcp_match_codec_list(&codecList , &pConnect->codecList , &pConnectTmp->codecList);
	
    if(ret < 0)
        return FALSE;	
	
	memcpy(&pConnect->codecList , &codecList , sizeof(MGC_CODEC_LIST));		
	pConnect->mediaAttr.vocoderType = codecList.codec[0];
	return TRUE;
}

BOOL mgc_connect_set_conn_mode(CONNECT_INFO *pConnect , MGC_CON_MODE mode)
{
    if(pConnect == NULL)
        return FALSE;

    if(mode == MGC_CON_MODE_OWN)
    {
        MGC_DEBUG("conn[%d] keep own mode %s" , pConnect->id , mgc_mgcp_print_mgc_mode(pConnect->mediaAttr.conMode));
		return TRUE;
    }
	
    if(mode != pConnect->mediaAttr.conMode)
    {
        MGC_DEBUG("conn[%d] mode %s ==>> %s" , 
            pConnect->id , mgc_mgcp_print_mgc_mode(pConnect->mediaAttr.conMode ), mgc_mgcp_print_mgc_mode(mode));
	}
	
    pConnect->mediaAttr.conMode = mode;
	return TRUE;
}

MGC_CON_MODE mgc_connect_get_conn_mode(CONNECT_INFO *pConnect)
{
    if(pConnect == NULL)
	    return MGC_CON_MODE_UNDEF;

	return pConnect->mediaAttr.conMode;
}


/***************************************************************************
 * mgc_connect_rqnt_para_create
 * ------------------------------------------------------------------------
 * General:  create rqnt req msg
 * Return Value:  if failure return FALSE , else return TRUE
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 *           pPara - the MGCP para need to be write
 ***************************************************************************/
BOOL mgc_connect_rqnt_para_create(CONNECT_INFO *pConnect , MGCP_PARA *pPara)
{
    if((pConnect == NULL)||(pPara == NULL))
        return FALSE;

    /*set dest ip*/
    if(mgc_mgcp_create_connect_dest_ip(pConnect , pPara) == FALSE)
	    return FALSE;

    /*set port*/
    if(mgc_mgcp_create_connect_port(pConnect , pPara) == FALSE)
	    return FALSE;	
	
	/*create sl*/
	if(mgc_mgcp_create_connect_req_start_line(pConnect , pPara) == FALSE)
	    return FALSE;

    /*create pkg signal*/
    if(mgc_mgcp_create_connect_pkg_sig(pConnect , pPara) == FALSE)
	    return FALSE;	

    /*create pkg request*/
    if(mgc_mgcp_create_connect_pkg_req(pConnect , pPara) == FALSE)
        return FALSE;
	
    return TRUE;
}


/***************************************************************************
 * mgc_connect_auep_para_create
 * ------------------------------------------------------------------------
 * General:  create auep req msg
 * Return Value:  if failure return FALSE , else return TRUE
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 *           pPara - the MGCP para need to be write
 ***************************************************************************/
BOOL mgc_connect_auep_para_create(CONNECT_INFO *pConnect , MGCP_PARA *pPara)
{
    if((pConnect == NULL)||(pPara == NULL))
        return FALSE;

    /*set dest ip*/
    if(mgc_mgcp_create_connect_dest_ip(pConnect , pPara) == FALSE)
	    return FALSE;

    /*set port*/
    if(mgc_mgcp_create_connect_port(pConnect , pPara) == FALSE)
	    return FALSE;	
	
	/*create sl*/
	if(mgc_mgcp_create_connect_req_start_line(pConnect , pPara) == FALSE)
	    return FALSE;

    pPara->sl.trkNum = 0;
	pPara->sl.chlNum = 1;
    return TRUE;
}

/***************************************************************************
 * mgc_connect_crcx_para_create
 * ------------------------------------------------------------------------
 * General:  create crcx req msg
 * Return Value:  if failure return FALSE , else return TRUE
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 *           pPara - the MGCP para need to be write
 ***************************************************************************/
BOOL mgc_connect_crcx_para_create(CONNECT_INFO *pConnect , MGCP_PARA *pPara)
{
    MG_INFO *pMgInfo = NULL;
    if((pConnect == NULL)||(pPara == NULL))
        return FALSE;
    /*set dest ip*/
	if(mgc_mgcp_create_connect_dest_ip(pConnect , pPara) == FALSE)
	    return FALSE;
	
	/*set port*/
	if(mgc_mgcp_create_connect_port(pConnect , pPara) == FALSE)
	    return FALSE;	
	
	/*create sl*/
	if(mgc_mgcp_create_connect_req_start_line(pConnect , pPara) == FALSE)
	    return FALSE;
	
	/*create call id*/
	if(mgc_mgcp_create_connect_call_id(pConnect , pPara) == FALSE)
	    return FALSE;
	
	/*create conn mode*/
	if(mgc_mgcp_create_connect_con_mode(pConnect , pPara) == FALSE)
	    return FALSE;	
	
	/*create local opt*/
	if(mgc_mgcp_create_connect_local_opt(pConnect , pPara) == FALSE)
		return FALSE;

    /*special process for AAS crcx*/
	pMgInfo = mgc_connect_get_own_mg_info(pConnect);
    if(pMgInfo == NULL)	
	    return FALSE;

    if(pMgInfo->mgAttr.mgType == MGC_MG_TYPE_ANN)
    {    
         if(mgc_mgcp_create_connect_sdp(pConnect, pPara) == FALSE)
		     return TRUE;	
    }
	
    return TRUE;	
}

/***************************************************************************
 * mgc_connect_mdcx_para_create
 * ------------------------------------------------------------------------
 * General:  create mdcx req msg
 * Return Value:  if failure return FALSE , else return TRUE
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 *           pPara - the MGCP para need to be write
 ***************************************************************************/
BOOL mgc_connect_mdcx_para_create(CONNECT_INFO *pConnect , MGCP_PARA *pPara)
{
    MGCF_OPER_STEP *pOperStep = NULL;

    if((pConnect == NULL)||(pPara == NULL))
        return FALSE;

    if((mgc_connect_get_status(pConnect) != MGC_CONNECT_STATUS_CREATED)&&(mgc_connect_get_status(pConnect) != MGC_CONNECT_STATUS_CREATE))
	    return FALSE;	

    pOperStep = pConnect->pOperStep;
	if(pOperStep == NULL)
        return FALSE;

    mgc_connect_attr_negotiate(pConnect);
  
    /*set dest ip*/ 
    if(mgc_mgcp_create_connect_dest_ip(pConnect , pPara) == FALSE)
	    return FALSE;

	/*set port*/ 
	if(mgc_mgcp_create_connect_port(pConnect , pPara) == FALSE)
	    return FALSE;		

    /*create sl*/
    if(mgc_mgcp_create_connect_req_start_line(pConnect , pPara) == FALSE)
	    return FALSE;

	/*create call id*/ 
	if(mgc_mgcp_create_connect_call_id(pConnect , pPara) == FALSE)
	    return FALSE;	

	/*create conn mode*/	
    if(mgc_mgcp_create_connect_con_mode(pConnect , pPara) == FALSE)	 
	    return FALSE;	
    
    /*create conn id*/  
    if(mgc_mgcp_create_connect_con_id(pConnect , pPara) == FALSE)	 
	    return FALSE;		

	/*create local opt*/ 
	if(mgc_mgcp_create_connect_local_opt(pConnect , pPara) == FALSE)
		return FALSE;	

	/*create pkg signal*/ 
	if(mgc_mgcp_create_connect_pkg_sig(pConnect , pPara) == FALSE)
		return FALSE;		

	/*create sdp*/    
	if(mgc_mgcp_create_connect_sdp(pConnect , pPara) == FALSE)
		return FALSE;		

    if(( pConnect->flag & MGCP_PARA_FLAG_TFO) == MGCP_PARA_FLAG_TFO)
    {
        pPara->flag |= MGCP_PARA_FLAG_TFO;
    }
    
    return TRUE;
}


/***************************************************************************
 * mgc_connect_dlcx_para_create
 * ------------------------------------------------------------------------
 * General:  create dlcx req msg
 * Return Value:  if failure return FALSE , else return TRUE
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 *           pPara - the MGCP para need to be write
 ***************************************************************************/
BOOL mgc_connect_dlcx_para_create(CONNECT_INFO *pConnect , MGCP_PARA *pPara)
{
	
    if((pConnect == NULL)||(pPara == NULL))
        return FALSE;

    /*set dest ip*/
    if(mgc_mgcp_create_connect_dest_ip(pConnect , pPara) == FALSE)
	    return FALSE;

	/*set port*/
	if(mgc_mgcp_create_connect_port(pConnect , pPara) == FALSE)
	    return FALSE;		

    /*create sl*/
    if(mgc_mgcp_create_connect_req_start_line(pConnect , pPara) == FALSE)
	    return FALSE;
	
	/*create call id*/
	if(mgc_mgcp_create_connect_call_id(pConnect , pPara) == FALSE)
	    return FALSE;	

    /*create conn id*/
    if(mgc_mgcp_create_connect_con_id(pConnect , pPara) == FALSE)	 
	    return FALSE;		

    /*create pkg signal*/
    if(mgc_mgcp_create_connect_pkg_sig(pConnect , pPara) == FALSE)
	    return FALSE;	

    return TRUE;
}


/***************************************************************************
 * mgc_connect_crcx_resp_parse_para
 * ------------------------------------------------------------------------
 * General:  parse crcx response
 * Return Value:  if failure return FALSE , else return TRUE
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 *           pPara - the MGCP para need to be parsed
 ***************************************************************************/
BOOL mgc_connect_crcx_resp_parse_para(CONNECT_INFO *pConnect , MGCP_PARA *pPara)
{

    if((pConnect == NULL)||(pPara == NULL))
        return FALSE;		


    /*record connection id*/
	if((pPara->flag & MGCP_PARA_FLAG_I) == MGCP_PARA_FLAG_I )
	{
	    sprintf(pConnect->mediaAttr.conId , "%s" , pPara->i.conId);
	}

	if((pPara->flag & MGCP_PARA_FLAG_O) == MGCP_PARA_FLAG_O)
	{
	    pConnect->mediaAttr.pkgEvent.pkg = pPara->o.package;
		pConnect->mediaAttr.pkgEvent.event = pPara->o.event;
	}

    if((pPara->flag & MGCP_PARA_FLAG_SDP) == MGCP_PARA_FLAG_SDP)
    {
        memcpy(&(pConnect->mediaAttr.sdp) , &pPara->sdp , sizeof(PUB_SDP_MSG));
    }

    return TRUE;
}

/***************************************************************************
 * mgc_connect_mdcx_resp_parse_para
 * ------------------------------------------------------------------------
 * General:  parse mdcx response
 * Return Value:  if failure return FALSE , else return TRUE
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 *           pPara - the MGCP para need to be parsed
 ***************************************************************************/
BOOL mgc_connect_mdcx_resp_parse_para(CONNECT_INFO *pConnect , MGCP_PARA *pPara)
{

    if((pConnect == NULL)||(pPara == NULL))
        return FALSE;		


    /*record connection id*/
	if((pPara->flag & MGCP_PARA_FLAG_I) == MGCP_PARA_FLAG_I )
	{
	    sprintf(pConnect->mediaAttr.conId , "%s" , pPara->i.conId);
	}

	if((pPara->flag & MGCP_PARA_FLAG_O) == MGCP_PARA_FLAG_O)
	{
	    pConnect->mediaAttr.pkgEvent.pkg = pPara->o.package;
		pConnect->mediaAttr.pkgEvent.event = pPara->o.event;

	}

    if((pPara->flag & MGCP_PARA_FLAG_SDP) == MGCP_PARA_FLAG_SDP)
    {
        memcpy(&(pConnect->mediaAttr.sdp) , &pPara->sdp , sizeof(PUB_SDP_MSG));
    }

    return TRUE;
}


CONNECT_INFO *mgc_connect_find_conn_by_conid(MGCP_PARA *pPara)
{
    int i;
	CONNECT_INFO *pConnect = NULL;

    if(pPara == NULL)
        return NULL;

    if(strlen(pPara->i.conId) == 0)
        return NULL;
		
    for( i=0 ; i<MGC_MAX_NUM_OF_CON ; i++)
    {
        pConnect = &mgcConnectInfo[i];

        if(pConnect->pChnlInfo == NULL)
		    continue;

		if((mgc_connect_get_status(pConnect) != MGC_CONNECT_STATUS_CREATED)&&(mgc_connect_get_status(pConnect) != MGC_CONNECT_STATUS_CREATE))
		    continue;

        if(strcmp(pConnect->mediaAttr.conId , pPara->i.conId) != 0)
		    continue;

		return pConnect;
    }

	return pConnect;
}


/***************************************************************************
 * mgc_connect_assign_conn_by_para
 * ------------------------------------------------------------------------
 * General:  assign an conncet to handle incoming MGCP req
 * Return Value:  if failure return FALSE , else return TRUE
 * ------------------------------------------------------------------------
 * Arguments:
 * Input:  pPara - the MGCP para need to be parsed
 ***************************************************************************/
CONNECT_INFO *mgc_connect_assign_conn_by_para(MGCP_PARA *pPara)
{
    PHY_PORT_INFO *pPhyPort = NULL;
	CONNECT_INFO *pConnect = NULL;
	CHNL_INFO *pChnlInfo = NULL;
	MGCP_SL *pSl = NULL;
	
    if(pPara == NULL)
        return NULL;		

    pSl = &pPara->sl;
	MGC_DEBUG("enter %s " , __FUNCTION__);
	MGC_DEBUG("alloc res to mg:%s port %d chnl %d" , pSl->mgName, pSl->trkNum, pSl->chlNum);
	if(pSl->epNameMethod == MGCP_EP_NAME_STRUCTURED)
	{
	    pPhyPort = mgc_mg_info_find_port_by_name_and_portNo(pSl->mgName, pSl->trkNum, pPara->localPort);
	}
    else
    {
        pPhyPort = mgc_mg_info_find_port_by_name(pSl->mgName , pPara->localPort);
    }
    if(pPhyPort == NULL)
	    return NULL;

    pChnlInfo = mgc_chnl_info_find_chnl_of_phy(pPhyPort, pSl->chlNum);
	if(pChnlInfo == NULL)
	    return NULL;	

    pConnect = mgc_chnl_info_assign_idle_connect(pChnlInfo);
	if(pConnect == NULL)
	    return NULL;	

	MGC_DEBUG("conn[%d] is assigend" , pConnect->id);
    return pConnect;
}




/***************************************************************************
 * mgc_connect_crcx_req_parse_para
 * ------------------------------------------------------------------------
 * General:  parse crcx  req
 * Return Value:  if failure return FALSE , else return TRUE
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 *           pPara - the MGCP para need to be parsed
 ***************************************************************************/
BOOL mgc_connect_crcx_req_parse_para(CONNECT_INFO *pConnect , MGCP_PARA *pPara)
{
    if((pConnect == NULL)||(pPara == NULL))
        return FALSE;

    if(mgc_mgcp_parse_connect_local_opt(pConnect, pPara) == FALSE)
	    return FALSE;	

    if(mgc_mgcp_parse_connect_mode(pConnect, pPara) == FALSE)
	    return FALSE;	

    if(mgc_mgcp_parse_connect_call_id(pConnect, pPara) == FALSE)
	    return FALSE;	

    if(mgc_mgcp_parse_connect_pkg_event(pConnect, pPara) == FALSE)
	    return FALSE;	

    if(mgc_mgcp_parse_connect_pkg_sig(pConnect, pPara) == FALSE)
	    return FALSE;	

    if(mgc_mgcp_parse_connect_sdp(pConnect, pPara) == FALSE)
	    return FALSE;		

    return TRUE;
}

/***************************************************************************
 * mgc_connect_mdcx_req_parse_para
 * ------------------------------------------------------------------------
 * General:  parse mdcx req
 * Return Value:  if failure return FALSE , else return TRUE
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 *           pPara - the MGCP para need to be parsed
 ***************************************************************************/
BOOL mgc_connect_mdcx_req_parse_para(CONNECT_INFO *pConnect , MGCP_PARA *pPara)
{
    if((pConnect == NULL)||(pPara == NULL))
        return FALSE;

    if(mgc_mgcp_parse_connect_local_opt(pConnect, pPara) == FALSE)
	    return FALSE;	

    if(mgc_mgcp_parse_connect_mode(pConnect, pPara) == FALSE)
	    return FALSE;	

    if(mgc_mgcp_parse_connect_call_id(pConnect, pPara) == FALSE)
	    return FALSE;	

    if(mgc_mgcp_parse_connect_pkg_event(pConnect, pPara) == FALSE)
	    return FALSE;	

    if(mgc_mgcp_parse_connect_pkg_sig(pConnect, pPara) == FALSE)
	    return FALSE;	

    if(mgc_mgcp_parse_connect_sdp(pConnect, pPara) == FALSE)
	    return FALSE;		

    return TRUE;
}

/***************************************************************************
 * mgc_connect_req_parse_para
 * ------------------------------------------------------------------------
 * General:  parse req
 * Return Value:  if failure return FALSE , else return TRUE
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 *           pPara - the MGCP para need to be parsed
 ***************************************************************************/
BOOL mgc_connect_req_parse_para(CONNECT_INFO *pConnect , MGCP_PARA *pPara)
{
    if((pConnect == NULL)||(pPara == NULL))
        return FALSE;
	
    if(mgc_mgcp_parse_connect_local_opt(pConnect, pPara) == FALSE)
	    return FALSE;	
	
    if(mgc_mgcp_parse_connect_mode(pConnect, pPara) == FALSE)
	    return FALSE;	

    if(mgc_mgcp_parse_connect_call_id(pConnect, pPara) == FALSE)
	    return FALSE;	

    if(mgc_mgcp_parse_connect_pkg_event(pConnect, pPara) == FALSE)
	    return FALSE;	

    if(mgc_mgcp_parse_connect_pkg_sig(pConnect, pPara) == FALSE)
	    return FALSE;	

    if(mgc_mgcp_parse_connect_sdp(pConnect, pPara) == FALSE)
	    return FALSE;		
	
    return TRUE;
}


/***************************************************************************
 * mgc_connect_rec_mgcp_tag
 * ------------------------------------------------------------------------
 * General:  record MGCP msg tag
 * Return Value:  if failure return FALSE , else return TRUE
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 *           pPara - the MGCP para need to be record
 ***************************************************************************/
BOOL mgc_connect_rec_mgcp_tag(CONNECT_INFO *pConnect , MGCP_PARA *pPara)
{
    MGCP_REC_TAG *pRecTag = NULL;
	PUB_SDP_MSG *pSdp = NULL;
    MGC_TANDEM_INFO *pTandem = NULL;
	
    if((pConnect == NULL)||(pPara == NULL))
        return FALSE;

    pRecTag = &pConnect->mgcpRec;
    pSdp = &pPara->sdp;
    memcpy(&pRecTag->mode , &pPara->m , sizeof(MGCP_M));
	memcpy(&pRecTag->c, &pSdp->c, sizeof(MGCP_C));
    memcpy(&pRecTag->m, &(pSdp->medias.medias[0]) , sizeof(PUB_SDP_MEDIA));		

    if(pConnect->pTandem == NULL)
	    return TRUE;

	pTandem = pConnect->pTandem;

	if(mgc_tandem_info_get_conn_pos(pTandem, pConnect) == MGC_TANDEM_CONN_POS_RX)
	{
	    sprintf(pRecTag->esCci , "%s" , pTandem->escci);            
	}

	if(mgc_tandem_info_get_conn_pos(pTandem, pConnect) == MGC_TANDEM_CONN_POS_TX)
	{
	    sprintf(pRecTag->esCci , "%s" , pTandem->escci);            
	}
    	
    return TRUE;
}

/***************************************************************************
 * mgc_connect_is_mgcp_tag_same
 * ------------------------------------------------------------------------
 * General:  check whether the MGCP msg it the same with the fomer one
 * Return Value:  if failure return FALSE , else return TRUE
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 *           pPara - the MGCP para need to be parsed
 ***************************************************************************/
BOOL mgc_connect_is_mgcp_tag_same(CONNECT_INFO *pConnect , MGCP_PARA *pPara)
{
    MGCP_REC_TAG *pRecTag = NULL;
	PUB_SDP_MSG *pSdp = NULL;	
    MGC_TANDEM_INFO *pTandem = NULL;
	
    if((pConnect == NULL)||(pPara == NULL))
        return FALSE;

    pRecTag = &pConnect->mgcpRec;
    pSdp = &pPara->sdp;

    if(pRecTag->mode.mode != pPara->m.mode)
	    return FALSE;	

    if(pRecTag->m.m.port != pSdp->medias.medias[0].m.port )
	    return FALSE;
	
    if(pRecTag->m.m.payloads[0] != pSdp->medias.medias[0].m.payloads[0])
	    return FALSE;

    if(strcmp(pRecTag->c.addr , pSdp->c.addr) != 0)
	    return FALSE;

    if(pConnect->pTandem == NULL)
	    return TRUE;


	pTandem = pConnect->pTandem;

	if(mgc_tandem_info_get_conn_pos(pTandem, pConnect) == MGC_TANDEM_CONN_POS_RX)
	{
        if(strcmp(pRecTag->esCci , pTandem->escci) != 0)
		    return FALSE;
	}

	if(mgc_tandem_info_get_conn_pos(pTandem, pConnect) == MGC_TANDEM_CONN_POS_TX)
	{
        if(strcmp(pRecTag->esCci , pTandem->escci) != 0)
		    return FALSE;
	}

    return TRUE;	
}

/***************************************************************************
 * mgc_connect_is_conn_need_update
 * ------------------------------------------------------------------------
 * General:  check whether the connection need to update
 * Return Value:  if failure return FALSE , else return TRUE
 * ------------------------------------------------------------------------
 * Arguments:
 * Input: 	pConnct - the pointer of the CONNCET_INFO object
 *           pPara - the MGCP para need to be parsed
 ***************************************************************************/
BOOL mgc_connect_is_conn_need_update(CONNECT_INFO *pConnect , MGCP_PARA *pPara)
{
    if((pConnect == NULL)||(pPara == NULL))
        return FALSE;

    if(mgc_connect_is_mgcp_tag_same(pConnect , pPara) == TRUE)
	    return FALSE;	

    mgc_connect_rec_mgcp_tag(pConnect, pPara);
	return TRUE;
}


BOOL mgc_connect_add_auep(CONNECT_INFO *pConnect, PORT_INFO *pPortInfo)
{
    MGCF_STEP_INFO stepInfo;

    if((pConnect == NULL)||(pPortInfo == NULL))
	    return FALSE;	

    if(mgc_connect_get_own_chnl_info(pConnect) == NULL)
	    return FALSE;	

    if(mgc_connect_get_status(pConnect) != MGC_CONNECT_STATUS_IDLE)
	    return TRUE;	

    if(pConnect->pOperStep != NULL)
	     return TRUE;

    mgc_port_info_set_step_info(&stepInfo , MGC_CMD_AUEP, NULL, MGC_OPERA_NO_DELAY, MGC_CON_MODE_RECVONLY,
			                     NULL, NULL, NULL);
	
    if(mgc_port_info_add_opera_to_port(pPortInfo , pConnect, &stepInfo) == FALSE)
        return FALSE;

	return TRUE;
}


BOOL mgc_connect_add_crcx_with_mode(CONNECT_INFO *pConnect, MGC_CON_MODE mode ,PORT_INFO *pPortInfo)
{
    MGCF_STEP_INFO stepInfo;

    if((pConnect == NULL)||(pPortInfo == NULL))
	    return FALSE;	

    if(mgc_connect_get_own_chnl_info(pConnect) == NULL)
	    return FALSE;		

    if((mgc_connect_get_status(pConnect) == MGC_CONNECT_STATUS_CREATED)||(mgc_connect_get_status(pConnect) == MGC_CONNECT_STATUS_CREATE))
	    return TRUE;	

    mgc_port_info_set_step_info(&stepInfo , MGC_CMD_CRCX, NULL, MGC_OPERA_NO_DELAY, mode,
			                     NULL, NULL, NULL);
	
    if(mgc_port_info_add_opera_to_port(pPortInfo , pConnect, &stepInfo) == FALSE)
        return FALSE;

	return TRUE;
}



BOOL mgc_connect_add_crcx(CONNECT_INFO *pConnect, PORT_INFO *pPortInfo)
{
    MGCF_STEP_INFO stepInfo;

    if((pConnect == NULL)||(pPortInfo == NULL))
	    return FALSE;	

    if(mgc_connect_get_own_chnl_info(pConnect) == NULL)
	    return FALSE;		

    if((mgc_connect_get_status(pConnect) == MGC_CONNECT_STATUS_CREATED)||(mgc_connect_get_status(pConnect) == MGC_CONNECT_STATUS_CREATE))
	    return TRUE;	

    mgc_port_info_set_step_info(&stepInfo , MGC_CMD_CRCX, NULL, MGC_OPERA_NO_DELAY, MGC_CON_MODE_RECVONLY,
			                     NULL, NULL, NULL);
	
    if(mgc_port_info_add_opera_to_port(pPortInfo , pConnect, &stepInfo) == FALSE)
        return FALSE;

	return TRUE;
}


BOOL mgc_connect_add_crcx_aas(CONNECT_INFO *pConnect, CONNECT_INFO *pPeerConnect, PORT_INFO *pPortInfo)
{
	MG_INFO *pPeerMgInfo;
    MGCF_STEP_INFO stepInfo;
	
    if((pConnect == NULL)||(pPeerConnect == NULL)||(pPortInfo == NULL))
	    return FALSE;

    pPeerMgInfo = mgc_connect_get_own_mg_info(pPeerConnect);
    if(pPeerMgInfo == NULL)
    {
        MGC_ERROR("lost peerConn in aas");
        return FALSE;
    }
	
    if(mgc_connect_get_own_chnl_info(pConnect) == NULL)
	    return FALSE;	

    mgc_port_info_set_step_info(&stepInfo , MGC_CMD_CRCX, pPeerConnect, MGC_OPERA_NO_DELAY, MGC_CON_MODE_SENDRECV,
			                     NULL, NULL, NULL);   

    switch(mgc_connect_get_status(pPeerConnect))
    {
        case MGC_CONNECT_STATUS_CREATING:
		case MGC_CONNECT_STATUS_CREATE:
		case MGC_CONNECT_STATUS_CREATED:
			 memcpy(&stepInfo.codecList , &pPeerConnect->codecList , sizeof(MGC_CODEC_LIST));
			 pConnect->mediaAttr.ptime = pPeerConnect->mediaAttr.ptime;
			 break;
		case MGC_CONNECT_STATUS_IDLE:
			 memcpy(&stepInfo.codecList , &pPeerMgInfo->mgAttr.codecList , sizeof(MGC_CODEC_LIST));
			 pConnect->mediaAttr.ptime = pPeerMgInfo->mgAttr.ptime;
			 break;
		default:
			 MGC_ERROR("conn[%d] is not allocated ", pPeerConnect->id);
			 return FALSE;
    }
	
    if(mgc_port_info_add_opera_to_port(pPortInfo , pConnect, &stepInfo) == FALSE)
        return FALSE;

	return TRUE;	
}

BOOL mgc_connect_add_mdcx_aas(CONNECT_INFO *pConnect, CONNECT_INFO *pPeerConnect,  PORT_INFO *pPortInfo)
{
    MGCF_STEP_INFO stepInfo;

    if((pConnect == NULL)||(pPeerConnect == NULL)||(pPortInfo == NULL))
	    return FALSE;
	
    if(mgc_connect_get_own_chnl_info(pConnect) == NULL)
	    return FALSE;	

    mgc_port_info_set_step_info(&stepInfo , MGC_CMD_MDCX, pPeerConnect, MGC_OPERA_NO_DELAY, MGC_CON_MODE_OWN,
			                     NULL, NULL, NULL);   

    if(mgc_port_info_add_opera_to_port(pPortInfo , pConnect, &stepInfo) == FALSE)
        return FALSE;

	return TRUE;	

}


BOOL mgc_connect_add_dlcx(CONNECT_INFO *pConnect, PORT_INFO *pPortInfo)
{
    MGCF_STEP_INFO stepInfo;

    if((pConnect == NULL)||(pPortInfo == NULL))
	    return FALSE;	

    if(mgc_connect_get_own_chnl_info(pConnect) == NULL)
	    return FALSE;	

    mgc_port_info_set_step_info(&stepInfo , MGC_CMD_DLCX, NULL, MGC_OPERA_NO_DELAY, MGC_CON_MODE_INACTIVE,
			                     NULL, NULL, NULL);
	
    if(mgc_port_info_add_opera_to_port(pPortInfo , pConnect, &stepInfo) == FALSE)
        return FALSE;

	return TRUE;
}


BOOL mgc_connect_add_mdcx(CONNECT_INFO *pConnect, CONNECT_INFO *pPeerConnect , MGC_CON_MODE mode, PORT_INFO *pPortInfo)
{
    MGCF_STEP_INFO stepInfo;

    if((pConnect == NULL)||(pPeerConnect == NULL)||(pPortInfo == NULL))
	    return FALSE;

    if(mgc_connect_get_own_chnl_info(pConnect) == NULL)
	    return FALSE;	

    mgc_port_info_set_step_info(&stepInfo , MGC_CMD_MDCX, pPeerConnect, MGC_OPERA_NO_DELAY, mode,
			                     NULL, NULL, NULL);   

    if(mgc_port_info_add_opera_to_port(pPortInfo , pConnect, &stepInfo) == FALSE)
        return FALSE;

	return TRUE;	
}


BOOL mgc_connect_add_nop_with_delay(CONNECT_INFO *pConnect, DWORD delay , PORT_INFO *pPortInfo)
{
    MGCF_STEP_INFO stepInfo;

    if((pConnect == NULL)||(pPortInfo == NULL))
	    return FALSE;	

    if(mgc_connect_get_own_chnl_info(pConnect) == NULL)
	    return FALSE;	

    mgc_port_info_set_step_info(&stepInfo , MGC_CMD_NOP, NULL, delay, MGC_CON_MODE_OWN,
			                     NULL, NULL, NULL);
	
    if(mgc_port_info_add_opera_to_port(pPortInfo , pConnect, &stepInfo) == FALSE)
        return FALSE;

    MGC_DEBUG("conn[%d] will suspend %ld" , pConnect->id , delay);
	return TRUE;
}

BOOL mgc_connect_add_nop(CONNECT_INFO *pConnect, PORT_INFO *pPortInfo)
{
    MGCF_STEP_INFO stepInfo;

    if((pConnect == NULL)||(pPortInfo == NULL))
	    return FALSE;	

    if(mgc_connect_get_own_chnl_info(pConnect) == NULL)
	    return FALSE;	

    mgc_port_info_set_step_info(&stepInfo , MGC_CMD_NOP, NULL, MGC_OPERA_NO_DELAY, MGC_CON_MODE_OWN,
			                     NULL, NULL, NULL);
	
    if(mgc_port_info_add_opera_to_port(pPortInfo , pConnect, &stepInfo) == FALSE)
        return FALSE;

	return TRUE;
}



BOOL mgc_connect_add_rqnt(CONNECT_INFO *pConnect, PKG_EVENT *pPkgEvent, PKG_SIGNAL *pPkgSig, PORT_INFO *pPortInfo)
{
    MGCF_STEP_INFO stepInfo;

    if((pConnect == NULL)||(pPortInfo == NULL))
	    return FALSE;	

    if(mgc_connect_get_own_chnl_info(pConnect) == NULL)
	    return FALSE;	

    mgc_port_info_set_step_info(&stepInfo, MGC_CMD_RQNT, NULL, MGC_OPERA_NO_DELAY, MGC_CON_MODE_SENDRECV,
		                        pPkgEvent, pPkgSig, NULL);
	
    if(mgc_port_info_add_opera_to_port(pPortInfo , pConnect, &stepInfo) == FALSE)
        return FALSE;

	return TRUE;
}


BOOL mgc_connect_add_rqnt_with_delay(CONNECT_INFO *pConnect, WORD delay, PKG_EVENT *pPkgEvent, PKG_SIGNAL *pPkgSig, PORT_INFO *pPortInfo)
{
    MGCF_STEP_INFO stepInfo;

    if((pConnect == NULL)||(pPortInfo == NULL))
	    return FALSE;	

    if(mgc_connect_get_own_chnl_info(pConnect) == NULL)
	    return FALSE;	

    mgc_port_info_set_step_info(&stepInfo, MGC_CMD_RQNT, NULL, delay, MGC_CON_MODE_SENDRECV,
		                        pPkgEvent, pPkgSig, NULL);
	
    if(mgc_port_info_add_opera_to_port(pPortInfo , pConnect, &stepInfo) == FALSE)
        return FALSE;

	return TRUE;
}


CONNECT_INFO *mgc_connect_dup_attr(CONNECT_INFO *pConnect)
{
    CONNECT_INFO *pConnTmp = NULL;

    if(pConnect == NULL)
        return NULL;

    pConnTmp = mgc_connect_get_unused();
    if(pConnTmp == NULL)	
        return NULL;		
    	

    pConnTmp->flag = pConnect->flag;
    pConnTmp->pChnlInfo = pConnect->pChnlInfo;
    pConnTmp->status = pConnect->status;
    return pConnTmp;
}


#ifdef MGC_TEST_ENABLE
int mgc_connect_inused_num(void)
{
    int i , num;
    CONNECT_INFO *pConnect = NULL;

    num = 0;
    for(i=0 ; i<MGC_MAX_NUM_OF_CON ; i++)
    {
        pConnect = &mgcConnectInfo[i];

		if(pConnect->pChnlInfo == NULL)
		    continue;

		num++;		
		MGC_DEBUG("conn[%d] in use" , pConnect->id);
    }
    return num;	
}
#endif

