#include "./include/mgc_pub.h"
#include "./include/mgc.h"
#include "./include/mgc_const.h"
#include "./include/mgc_ext.h"
#include "./include/mgc_struct.h"
#include "./include/mgc_debug.h"
#include "./include/mgc_sess_ctl.h"

extern void mgc_port_init(WORD port);
extern void mgc_connect_init(WORD connectIndex);
extern int mgc_is_non_virtual_mg(BYTE mgType);

void mgc_rpl_para_amr_sdp()
{
    int i;
    char tmp[64];
    char *dash;
    char *slash;

    for (i = 0; i < mgcMgcpPara.sdp.medias.medias[0].attrs.num; i++)
    {
        if (mgcMgcpPara.sdp.medias.medias[0].attrs.attrs[i].aType != PUB_SDP_ATTR_TYPE_RTPMAP)
            continue;

        if ((dash = strstr(mgcMgcpPara.sdp.medias.medias[0].attrs.attrs[i].aValue, "AMR_")) == NULL)
            continue;

        if ((slash = strchr(dash, '/')) != NULL)
        {
            strcpy(tmp, slash); 
            strcpy(dash+3, tmp);
        }

    }
}

int mgc_rtp_proxy_find_mgNo(MG_INFO *pMgInfo)
{
    int i;
	
    if(pMgInfo == NULL)
        return -1;	
    
    for (i = 1; i < MGC_MAX_NUM_OF_MG; i++)
    {
        if(&(mgcMgInfo[i]) == pMgInfo)
	        return i;		
    }
   
    return -1;
}



BOOL mgc_rtp_proxy_connection_find_own_chnl(CONNECT_INFO *pConn ,CHNL *pChnl)
{
    CHNL_INFO *pChnlInfo = NULL;	
	MG_INFO *pMgInfo = NULL;
	BOOL tag =FALSE;
	int i;
	
    if((pConn == NULL)||(pChnl == NULL))
        return FALSE;

    if(pConn->chlIndex>=MGC_MAX_NUM_OF_CHNL)
        return FALSE;		

    pChnlInfo = &mgcChnl[pConn->chlIndex];
    tag = FALSE;
    for(i=0 ; i<MGC_MAX_NUM_OF_CHNL_CON ; i++)
    {
        if(pConn == &mgcConnectInfo[pChnlInfo->connectIndex[i]])
        {
            pChnl->connectNo = i;
			tag = TRUE;
			break;
        }		
    }

    if(tag == FALSE)
        return FALSE;		
	
    pMgInfo = &(mgcMgInfo[pChnlInfo->mgNo]);
    i= mgc_rtp_proxy_find_mgNo(pMgInfo);
    if(i<0)
	    return FALSE;

	pChnl->mgNo = i;
	return TRUE;	
}




int mgc_create_para_call_id(PORT_INFO *portInfo, CONNECT_INFO *connectInfo)
{
    if (connectInfo->mediaAttr.callId[0] == '\0')
    {
        sprintf(connectInfo->mediaAttr.callId, "%X%lX", portInfo->usrPort, time(NULL));
    }
    
    strcpy(mgcMgcpPara.c.callId, connectInfo->mediaAttr.callId);
    
    mgcMgcpPara.flag |= MGCP_PARA_FLAG_C;
    
    return 0;
}

int mgc_create_para_con_id(PORT_INFO *portInfo, CONNECT_INFO *connectInfo)
{

    strcpy(mgcMgcpPara.i.conId, connectInfo->mediaAttr.conId);
    mgcMgcpPara.flag |= MGCP_PARA_FLAG_I;    
    
    return 0;
}

int mgc_create_para_local_opt(PORT_INFO *portInfo, CONNECT_INFO *connectInfo)
{
    CHNL chnl;
	MG_INFO *pMgInfo = NULL;
    if(connectInfo == NULL)
	    return -1;	

    if(mgc_rtp_proxy_connection_find_own_chnl(connectInfo , &chnl) == TRUE)
    {
        pMgInfo = &mgcMgInfo[chnl.mgNo];
    }

    if(pMgInfo == NULL)
	    return -1;		

    mgcMgcpPara.l.p = connectInfo->mediaAttr.ptime;
    
    if (connectInfo->mediaAttr.vocoderType > MGC_VCTYPE_MAX_1)
    {
        strcpy(mgcMgcpPara.l.codec, vcName[0]);
    }
    else
    {       
        strcpy(mgcMgcpPara.l.codec, vcName[connectInfo->mediaAttr.vocoderType]);
    }//add by Francis
    
     if(pMgInfo->mgAttr.mgType == MGC_MG_TYPE_IPBSS)
     {
        switch(connectInfo->mediaAttr.vocoderType)
        {
            case MGC_VCTYPE_AMR_12_2: 
			case MGC_VCTYPE_AMR_10_2:
			case MGC_VCTYPE_AMR_7_95:
			case MGC_VCTYPE_AMR_7_4:
			case MGC_VCTYPE_AMR_6_7:
			case MGC_VCTYPE_AMR_5_15:
			case MGC_VCTYPE_AMR_5_9:
			case MGC_VCTYPE_AMR_4_75:  				
				sprintf(mgcMgcpPara.l.codec , "AMR");
				break;
			default:
				break;
        }	 
     }
    
    mgcMgcpPara.l.ecDisable = connectInfo->mediaAttr.ecDisable;
    mgcMgcpPara.l.ssDisable = connectInfo->mediaAttr.ssDisable;
    mgcMgcpPara.flag |= MGCP_PARA_FLAG_L;
    
    return 0;
}

int mgc_create_para_con_mode(PORT_INFO *portInfo, CONNECT_INFO *connectInfo)
{
    if (connectInfo->mediaAttr.conMode > 3)//new replace
    {
        return -1;
    }//add by Francis
    
    mgcMgcpPara.m.mode = connectInfo->mediaAttr.conMode;    
    mgcMgcpPara.flag |= MGCP_PARA_FLAG_M;
    
    return 0;
}

int mgc_create_para_signal_request(PORT_INFO *portInfo, CHNL_INFO *chnlInfo)
{
    if (chnlInfo == NULL)
    {
        mgcMgcpPara.s.pkg = 0;
        mgcMgcpPara.s.signal = 0;
    }
    else
    {
	    if(portInfo->mgcfOperId == MGC_OPER_ID_CONNECT_CHNL)
	    {
	       mgcMgcpPara.r.pkg = chnlInfo->comMediaAttr.pkgReq>> 8;
	       mgcMgcpPara.r.event= chnlInfo->comMediaAttr.pkgReq & 0xFF;	
	       mgcMgcpPara.flag |= MGCP_PARA_FLAG_R;	
	       return 0;
        }

        if (MGC_OPER_ID_CONNECT_DTMF == portInfo->mgcfOperId)
        {
           mgcMgcpPara.r.pkg = chnlInfo->comMediaAttr.pkgReq>> 8;
           mgcMgcpPara.r.event= chnlInfo->comMediaAttr.pkgReq & 0xFF;   
           mgcMgcpPara.flag |= MGCP_PARA_FLAG_R;
        }

        mgcMgcpPara.s.pkg = chnlInfo->comMediaAttr.pkgSignal >> 8;
        mgcMgcpPara.s.signal = chnlInfo->comMediaAttr.pkgSignal & 0xFF;
    }
    mgcMgcpPara.flag |= MGCP_PARA_FLAG_S;
    return 0;
}

int mgc_create_para_sdp(PORT_INFO *portInfo, CONNECT_INFO *connectInfo, BYTE vocoderType)
{

    memcpy((BYTE *) &mgcMgcpPara.sdp, (BYTE *) &connectInfo->mediaAttr.sdp, sizeof(PUB_SDP_MSG));
/*
    switch (vocoderType)
    {
    case MGC_VCTYPE_PCMA:
       mgcMgcpPara.sdp.medias.medias[0].m.payloads[0] = 8;
	break;
    case MGC_VCTYPE_PCMU:
       mgcMgcpPara.sdp.medias.medias[0].m.payloads[0] = 0;
	break;
    case MGC_VCTYPE_GSM:
       mgcMgcpPara.sdp.medias.medias[0].m.payloads[0] = 3;
	break;
    case MGC_VCTYPE_GSM_EFR:
       mgcMgcpPara.sdp.medias.medias[0].m.payloads[0] = 84;
	break;
    case MGC_VCTYPE_AMR_12_2:
       mgcMgcpPara.sdp.medias.medias[0].m.payloads[0] = 71;
	break;
    case MGC_VCTYPE_G729B:
       mgcMgcpPara.sdp.medias.medias[0].m.payloads[0] = 118;
	break;
    case MGC_VCTYPE_AMR_10_2:
       mgcMgcpPara.sdp.medias.medias[0].m.payloads[0] = 70;
	break;
    case MGC_VCTYPE_AMR_7_95:
       mgcMgcpPara.sdp.medias.medias[0].m.payloads[0] = 69;
	break;
    case MGC_VCTYPE_AMR_7_4:
       mgcMgcpPara.sdp.medias.medias[0].m.payloads[0] = 68;
	break;
    case MGC_VCTYPE_AMR_6_7:
       mgcMgcpPara.sdp.medias.medias[0].m.payloads[0] = 67;
	break;
    case MGC_VCTYPE_AMR_5_15:
       mgcMgcpPara.sdp.medias.medias[0].m.payloads[0] = 65;
	break;
    case MGC_VCTYPE_AMR_5_9:
       mgcMgcpPara.sdp.medias.medias[0].m.payloads[0] = 66;
	break;
    case MGC_VCTYPE_AMR_4_75:
       mgcMgcpPara.sdp.medias.medias[0].m.payloads[0] = 64;
	break;
    default:
       break;
    }
*/	

    if (mgcMgInfo[portInfo->mgcfChnl.mgNo].mgAttr.mgType == MGC_MG_TYPE_IPBSS)
    {
        mgc_rpl_para_amr_sdp();
    }

    mgcMgcpPara.flag |= MGCP_PARA_FLAG_SDP;

    if ((mgcMgcpPara.sdp.flag & PUB_SDP_FLAG_O) == 0)
    {
        mgc_log_err("mgc_create_para_sdp: No SDP Flag !\n\r");
    }

    return 0;
}

int mgc_create_para_crcx(BYTE type, WORD port, WORD localConnectIndex)
{
    PORT_INFO   *portInfo;
    CONNECT_INFO    *connectInfo;
    MGCF_OPER_STEP *pStep;
	CHNL remChnl;
	MG_INFO *pMgInfo;
     WORD    remChnlIndex, phyPort , remConnIndex;	
    if (port >= MGC_MAX_NUM_OF_PORT)
    {
        return -1;
    }//add by Francis   
    
    portInfo = &mgcPort[port];
    connectInfo = &mgcConnectInfo[localConnectIndex];//new replace  
    


	
    if (type == MGCP_COMMAND)
    {
        if (mgc_create_para_con_mode(portInfo, connectInfo) < 0)        
        {
            return -1;
        }//add by Francis   

        mgc_create_para_call_id(portInfo, connectInfo);
        mgc_create_para_local_opt(portInfo, connectInfo);
        
        if ((mgcPort[port].mgcfOperId == MGC_OPER_ID_CONNECT_TONE) 
            || (mgcPort[port].mgcfOperId == MGC_OPER_ID_CONNECT_AAS))
        {   

            pStep = &portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex];
            memcpy(&remChnl , &pStep->remChnl , sizeof(remChnl));

            if(remChnl.mgNo > MGC_MAX_NUM_OF_MG)
            {
                mgc_log_err("mgc_create_para_crcx: invalid mgNo!\n\r");
		        return -1;
            }    

            if (remChnl.portNo >= MGC_MAX_PHY_PORT_PER_MG)
            {
	            mgc_log_err("mgc_create_para_crcx: invalid portNo!\n\r");
	            return -1;
            }

            if (remChnl.connectNo >= MGC_MAX_NUM_OF_CHNL_CON)
            {   
	            mgc_log_err("mgc_create_para_crcx: invalid connectNo!\n\r");
	            return -1;		
            }		

			
			pMgInfo = &mgcMgInfo[remChnl.mgNo];
			
			if ((MGC_MG_TYPE_ANN == pMgInfo->mgAttr.mgType)||(MGC_MG_TYPE_INTERNAL == pMgInfo->mgAttr.mgType))
			{
				remChnlIndex= pMgInfo->chnlStartIndex + remChnl.chlNo;
			}
			else
			{	
				phyPort = pMgInfo->portIndex[remChnl.portNo];
				remChnlIndex= mgcPhyPort[phyPort].chnlStartIndex + remChnl.chlNo;
			}	
			
     		remConnIndex= mgcChnl[remChnlIndex].connectIndex[remChnl.connectNo];			
			if(remConnIndex > MGC_MAX_NUM_OF_CON)	
	            return -1;	
            mgc_create_para_sdp(portInfo, &mgcConnectInfo[remConnIndex], connectInfo->mediaAttr.vocoderType);	
        }
    }
    else
    {
        mgc_create_para_con_id(portInfo, connectInfo);
        mgc_create_para_sdp(portInfo, connectInfo, connectInfo->mediaAttr.vocoderType);
    }
    
    return 0;
}

int mgc_create_para_mdcx(BYTE type, WORD port, WORD localChnlIndex, WORD remoteChnlIndex, WORD localConnectIndex, WORD remoteConnectIndex)
{
    PORT_INFO   *portInfo;
    CHNL_INFO   *localChnlInfo, *remoteChnlInfo;
    CONNECT_INFO    *localConnectInfo;
    CONNECT_INFO    *remoteConnectInfo; 
    
    if ((port >= MGC_MAX_NUM_OF_PORT) || (localChnlIndex >= mgcMaxChlNo))
    {
        return -1;
    }//add by Francis   
    
    portInfo = &mgcPort[port];
    localChnlInfo = &mgcChnl[localChnlIndex];
    remoteChnlInfo = &mgcChnl[remoteChnlIndex];
    localConnectInfo = &mgcConnectInfo[localConnectIndex]; 
    remoteConnectInfo = &mgcConnectInfo[remoteConnectIndex]; 
    
    
    if (type == MGCP_COMMAND)
    {
        if (mgc_create_para_con_mode(portInfo, localConnectInfo) < 0)       
        {
            return -1;
        }//add by Francis

        mgc_create_para_call_id(portInfo, localConnectInfo);
        mgc_create_para_con_id(portInfo, localConnectInfo);
        mgc_create_para_local_opt(portInfo, localConnectInfo);
        mgc_create_para_signal_request(portInfo, localChnlInfo);

//        if (localConnectInfo->mediaAttr.conMode >= MGCP_CON_MODE_SENDONLY)
        {
            mgc_create_para_sdp(portInfo, remoteConnectInfo, localConnectInfo->mediaAttr.vocoderType);
        }
        
        if ((portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].flag & MGCP_PARA_FLAG_TFO) == MGCP_PARA_FLAG_TFO)
        {
            mgcMgcpPara.flag |= MGCP_PARA_FLAG_TFO;
        }
    }
    
    return 0;
}

int mgc_create_para_dlcx(BYTE type, WORD port, WORD chnlIndex, WORD connectIndex)
{
    PORT_INFO   *portInfo;
    CHNL_INFO   *chnlInfo = NULL;
    CONNECT_INFO    *connectInfo;   
    
    if ((port >= MGC_MAX_NUM_OF_PORT) || (chnlIndex >= mgcMaxChlNo))
    {
        return -1;
    }//add by Francis   
    
    portInfo = &mgcPort[port];
    chnlInfo = &mgcChnl[chnlIndex];
    connectInfo = &mgcConnectInfo[connectIndex];
    
    if (type == MGCP_COMMAND)
    {
        if (chnlIndex < MGC_MAX_NUM_OF_CHNL)
        {
            if (0 == (portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].flag & 0x01))
            {
                mgc_create_para_call_id(portInfo, connectInfo);
                mgc_create_para_con_id(portInfo, connectInfo);
            }
        }
        mgc_create_para_signal_request(portInfo, chnlInfo);
    }
    
    return 0;
}

int mgc_create_para_rqnt(BYTE type, WORD port, WORD chnlIndex)
{
    PORT_INFO   *portInfo;
    CHNL_INFO   *chnlInfo;
    
    if ((port >= MGC_MAX_NUM_OF_PORT) || (chnlIndex >= mgcMaxChlNo))
    {
        return -1;
    }//add by Francis   
    
    portInfo = &mgcPort[port];
    chnlInfo = &mgcChnl[chnlIndex];
    
    if (type == MGCP_COMMAND)
        mgc_create_para_signal_request(portInfo, chnlInfo);
    
    return 0;
}

int mgc_create_para_auep(BYTE type, WORD port, WORD chnlIndex)
{
    return 0;
}

int mgc_create_para(BYTE type, WORD port, MG_ATTR *mgAttr, BYTE cmd)
{
    PORT_INFO   *portInfo;
    CHNL        remChnl;
    WORD        localChnlIndex = 0xFFFF, remoteChnlIndex;
    WORD        localConnectIndex;
    WORD        remoteConnectIndex; 
    
    if (port >= MGC_MAX_NUM_OF_PORT)
    {
        return -1;
    }//add by Francis
    
    portInfo = &mgcPort[port];
    
    if ((type == MGCP_RESPONSE)  && (mgcMgInfo[portInfo->mgcfChnl.mgNo].usrType == MGC_USER_TYPE_MG))
    {
        mgcMgcpPara.ip = portInfo->ip;
    }
    else
    {
        mgcMgcpPara.ip = mgAttr->ip;
    }

    if (mgcMgInfo[portInfo->mgcfChnl.mgNo].usrType == MGC_USER_TYPE_MGC)
    {
        mgcMgcpPara.localPort = MGC_MGCP_MGC_PORT;
        mgcMgcpPara.peerPort = MGC_MGCP_MG_PORT;
    }
    else
    {
        mgcMgcpPara.localPort = MGC_MGCP_MG_PORT;
        mgcMgcpPara.peerPort = MGC_MGCP_MGC_PORT;
    }
    mgcMgcpPara.flag = 0;
    
    mgcMgcpPara.sl.cmdRes = type;
    if (type == MGCP_COMMAND)
    {
        mgcMgcpPara.sl.epNameMethod = mgAttr->epDes;
        mgcMgcpPara.sl.mgType = mgAttr->mgType;
        if (mgc_is_non_virtual_mg(mgAttr->mgType))
        {   
            mgcMgcpPara.sl.portType = mgcPhyPort[mgcMgInfo[portInfo->mgcfChnl.mgNo].portIndex[portInfo->mgcfChnl.portNo]].portType;
        }
        else
        {
            mgcMgcpPara.sl.portType = 0; 
        }//add by Francis
        mgcMgcpPara.sl.trkNum = portInfo->mgcfChnl.portNo;
        mgcMgcpPara.sl.chlNum = portInfo->mgcfChnl.chlNo;
        strcpy(mgcMgcpPara.sl.mgName, mgAttr->domain);
    }
    else
        mgcMgcpPara.sl.retCode = portInfo->usrCmd;
        
    mgcMgcpPara.flag |= MGCP_PARA_FLAG_SL;
    
    if (portInfo->mgcfChnl.chlNo < MGC_MAX_NUM_OF_CHNL)
    {
        if ((MGC_MG_TYPE_ANN == mgcMgInfo[portInfo->mgcfChnl.mgNo].mgAttr.mgType) 
            || (MGC_MG_TYPE_INTERNAL == mgcMgInfo[portInfo->mgcfChnl.mgNo].mgAttr.mgType))
        {
            localChnlIndex = mgcMgInfo[portInfo->mgcfChnl.mgNo].chnlStartIndex + portInfo->mgcfChnl.chlNo;
        }
        else
        {   
            localChnlIndex = mgcPhyPort[mgcMgInfo[portInfo->mgcfChnl.mgNo].portIndex[portInfo->mgcfChnl.portNo]].chnlStartIndex + portInfo->mgcfChnl.chlNo;
        }
    }

    if ((MGCP_CMD_RQNT != cmd) && (MGCP_CMD_NTFY != cmd) && (MGCP_CMD_AUEP != cmd) && (MGCP_CMD_RSIP != cmd))   
    {
        localConnectIndex = mgcChnl[localChnlIndex].connectIndex[portInfo->mgcfChnl.connectNo];
    
        if (localConnectIndex >= MGC_MAX_NUM_OF_CON)
        {
            mgc_log_err("mgc_create_para: localConnectIndex out of range!\n\r");
            return -1;
        }
    }
    
    switch (cmd)
    {
    case MGCP_CMD_CRCX:
        mgc_create_para_crcx(type, port, localConnectIndex);        
        break;
    case MGCP_CMD_MDCX:
        remChnl = portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].remChnl;
        if ((MGC_MG_TYPE_INTERNAL != mgcMgInfo[remChnl.mgNo].mgAttr.mgType) && (MGC_MG_TYPE_ANN != mgcMgInfo[remChnl.mgNo].mgAttr.mgType))
            remoteChnlIndex = mgcPhyPort[mgcMgInfo[remChnl.mgNo].portIndex[remChnl.portNo]].chnlStartIndex + remChnl.chlNo;
        else
            remoteChnlIndex = mgcMgInfo[remChnl.mgNo].chnlStartIndex + remChnl.chlNo;

        remoteConnectIndex = mgcChnl[remoteChnlIndex].connectIndex[remChnl.connectNo];                  
//        if (mgcConnectInfo[localConnectIndex].mediaAttr.conMode >= MGCP_CON_MODE_SENDONLY)
        { 
            if (remoteConnectIndex >= MGC_MAX_NUM_OF_CON)
            {
                mgc_log_err("mgc_create_para: remoteConnectIndex out of range!\n\r");
                return -1;
            }
        }

        mgc_create_para_mdcx(type, port, localChnlIndex, remoteChnlIndex, localConnectIndex, remoteConnectIndex);
        break;
    case MGCP_CMD_DLCX:
        mgc_create_para_dlcx(type, port, localChnlIndex, localConnectIndex);
        break;
    case MGCP_CMD_RQNT:
        mgc_create_para_rqnt(type, port, localChnlIndex);
        break;
    case MGCP_CMD_AUEP:
        mgc_create_para_auep(type, port, localChnlIndex);
        break;
    }
    
    return 0;
}


int mgc_update_connect_media_by_step(WORD port, BYTE savPort, CHNL mgcfChnl, MGCF_OPER_STEP *currOperStep)
{
    WORD portIndex, chnlIndex;
    WORD connectIndex;
    PORT_INFO   *portInfo;
    
    portInfo = &mgcPort[port];
    
    if ((MGC_MG_TYPE_ANN == mgcMgInfo[mgcfChnl.mgNo].mgAttr.mgType) 
        || (MGC_MG_TYPE_INTERNAL == mgcMgInfo[mgcfChnl.mgNo].mgAttr.mgType))
    {
        chnlIndex = mgcMgInfo[mgcfChnl.mgNo].chnlStartIndex + mgcfChnl.chlNo;
    }
    else
    {       
        portIndex = mgcMgInfo[mgcfChnl.mgNo].portIndex[mgcfChnl.portNo];
        chnlIndex = mgcPhyPort[portIndex].chnlStartIndex + mgcfChnl.chlNo;
    }
    
    if (savPort == MGC_CHNL_CLEAR_PORT)
    {
        if (portInfo->mngCmd == MGC_MNG_CMD_OVERWRITE)
        {
            portInfo->mngCmd = MGC_MNG_CMD_IDLE;
        }
        
        if ((portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].cmd != MGCP_CMD_AUEP) && (portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].cmd != MGCP_CMD_RQNT) 
            && (portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].cmd != MGCP_CMD_RSIP))
        {
            connectIndex = mgcChnl[chnlIndex].connectIndex[mgcfChnl.connectNo];
            mgcConnectInfo[connectIndex].port = 0xFFFF;
            mgcChnl[chnlIndex].port = 0xFFFF;
            
            if ((portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].cmd == MGCP_CMD_DLCX)
                 && (0 == (portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].flag & 0x01)))
            {   
                mgcChnl[chnlIndex].connectIndex[mgcfChnl.connectNo] = 0xFFFF;
            }
        }
        else
        {
            mgcChnl[chnlIndex].port = 0xFFFF;
        }
        return 0;
    }
    else
    {
        if ((currOperStep->cmd == MGCP_CMD_AUEP) || (currOperStep->cmd == MGCP_CMD_RQNT) || (currOperStep->cmd == MGCP_CMD_RSIP))
        {
            mgcChnl[chnlIndex].port = port;
        }
        else
        {       
            connectIndex = mgcChnl[chnlIndex].connectIndex[mgcfChnl.connectNo];
                
            mgcConnectInfo[connectIndex].port = port;
            mgcChnl[chnlIndex].port = port;

            mgcConnectInfo[connectIndex].mediaAttr.ptime = currOperStep->media.ptime;
            mgcConnectInfo[connectIndex].mediaAttr.conMode = currOperStep->media.conMode;
            mgcConnectInfo[connectIndex].mediaAttr.vocoderType = currOperStep->media.vocoderType.codec[0];
            mgcConnectInfo[connectIndex].mediaAttr.pkgSignal = currOperStep->pkgSignal;         
        }
    }

    mgcChnl[chnlIndex].comMediaAttr.pkgSignal = currOperStep->pkgSignal;
    
    return 0;
}

BYTE mgc_mgcf_request(WORD port, BYTE *clrFlag, BYTE *mgcInsert)
{
    PORT_INFO   *portInfo;
    MG_ATTR     *mgAttr;
    BYTE        sapIndex;
    WORD        cmd, res;
    int         llPort;
    WORD        portIndex = 0xFFFF;
    WORD        chnlIndex = 0xFFFF;
    char        tmpStr[128];
    int         i;
    WORD        connectIndex = 0xFFFF;
    BYTE        toneNo, oldMode;
    CHNL        aasOrgChnl;

    WORD        aasPhyPortOrg;

    WORD        aasChnlIndexOrg;

	WORD        aasOrgConnectIndex;
    
    if (port >= MGC_MAX_NUM_OF_PORT)
    {
        return 0;
    }//add by Francis
    
    portInfo = &mgcPort[port];
    mgAttr = &mgcMgInfo[portInfo->mgcfChnl.mgNo].mgAttr;
    
    if ((MGC_MG_TYPE_ANN == mgAttr->mgType) 
        || (MGC_MG_TYPE_INTERNAL == mgAttr->mgType))
    {
        chnlIndex = mgcMgInfo[portInfo->mgcfChnl.mgNo].chnlStartIndex + portInfo->mgcfChnl.chlNo;   
    }
    else
    {   
        portIndex = mgcMgInfo[portInfo->mgcfChnl.mgNo].portIndex[portInfo->mgcfChnl.portNo];
        if ((portIndex < MGC_MAX_NUM_OF_PHY_PORT) 
            && (portInfo->mgcfChnl.chlNo < MGC_MAX_NUM_OF_CHNL))
            chnlIndex = mgcPhyPort[portIndex].chnlStartIndex + portInfo->mgcfChnl.chlNo;
    }   
    
    *clrFlag  = 0;

    if (chnlIndex >= MGC_MAX_NUM_OF_CHNL)
        return 2;
    
    if ((portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].cmd != MGCP_CMD_AUEP)
        && (portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].cmd != MGCP_CMD_RSIP))
    {    	
        if (((portInfo->mgcfChnl.connectNo >= MGC_MAX_NUM_OF_CHNL_CON)) 
        	|| (portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].chnlConnectIndex != portInfo->mgcfChnl.connectNo)
            || ((connectIndex = mgcChnl[chnlIndex].connectIndex[portInfo->mgcfChnl.connectNo]) >= MGC_MAX_NUM_OF_CON))
        {
//          *clrFlag  = 1;    
            return 2;
        }
    }   

    if (portInfo->mgcfOperStepsNum >= MGC_MAX_OPER_STEPS_NUM)
    {
        mgc_log_err("mgc_mgcf_request: OperStepsNum out of range!\n\r");        
        *clrFlag  = 1;    
        return 2;       
    }
    
    switch (portInfo->mgcfState2)
    {
    case 0:
        cmd = portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].cmd;     
        
        if (cmd != MGCP_CMD_AUEP)
        {
            if (chnlIndex < MGC_MAX_NUM_OF_CHNL)
            {
                if (((cmd != MGCP_CMD_RQNT) && (cmd != MGCP_CMD_RSIP) && (mgcConnectInfo[connectIndex].port < MGC_MAX_NUM_OF_PORT))
                    || (((cmd == MGCP_CMD_RQNT) || (cmd == MGCP_CMD_RSIP)) && (mgcChnl[chnlIndex].port < MGC_MAX_NUM_OF_PORT))) 
                {
                    if (portInfo->mgcfTimer == 0)
                        portInfo->mgcfTimer = MGC_MGCF_TIMER_20S;
                    else if (--portInfo->mgcfTimer == 0)
                    {
                        *clrFlag  = 1;//    
                        return 2;
                    }
                    return 0;
                }
                else if (cmd == MGCP_CMD_CRCX)
                {
                    if ((mgcConnectInfo[connectIndex].status == MGC_CONNECT_STATUS_CREATED)||(mgcConnectInfo[connectIndex].status == MGC_CONNECT_STATUS_TONE))                  
                    {
                        *clrFlag = 0;//
                        return 1;
                    }
                    else
                        portInfo->mgcfTimer = 0;
                }

				oldMode = mgcConnectInfo[connectIndex].mediaAttr.conMode;
                mgc_update_connect_media_by_step(port, MGC_CHNL_SAVE_PORT, mgcPort[port].mgcfChnl, &mgcPort[port].mgcfOperSteps[mgcPort[port].mgcfOperStepIndex]);              
            }
        }
        
		MGCF_OPER_STEP *pStep;
		pStep = &mgcPort[port].mgcfOperSteps[mgcPort[port].mgcfOperStepIndex];
		
		
        mgc_create_para(MGCP_COMMAND, port, mgAttr, cmd);

        if(cmd == MGCP_CMD_MDCX)
			{
 		    if(mgc_sess_is_chnl_need_update(pStep->localChnl , &mgcMgcpPara) == FALSE)
				{				   
                    *clrFlag = 1;					
					return 1;
				}					
			}		
        
        if ((llPort = MGCP_req(mgcMgcpSapIndex, cmd, port, &mgcMgcpPara)) < 0)
        {
            sprintf(tmpStr, "mgc_mgcf_request: MGCP_req failed, cmd: %d, usrPort: %d, port = %d\n\r", cmd, portInfo->usrPort, port);
            mgc_log_err(tmpStr);
            
            if (cmd != MGCP_CMD_AUEP)
            {
                if (MGC_MG_TYPE_ANN == mgAttr->mgType)
                {
//                  sapIndex = mgcMgInfo[portInfo->mgcfChnl.mgNo].sapIndex;
                    sapIndex = mgcChnl[chnlIndex].sapIndex;
                }
                else
                {
                    sapIndex = mgcPhyPort[portIndex].sapIndex;
                }               
                
                if (mgcSap[sapIndex].mgc_cnf != NULL)
                    mgcSap[sapIndex].mgc_cnf(portInfo->usrPort, port, portInfo->mgcfOperId, MGC_OPER_FAILURE, MGCP_RET_CODE_TRANS_TIME_OUT);
                *clrFlag  = 1;
            }
            else    // AUEP
            {
                mgcChnl[chnlIndex].auepSt = MGC_CHNL_AUEP_IDLE;
                *clrFlag  = 0;
            }
            return 2;
        }
        
        sprintf(tmpStr, "mgc_mgcf_request: send mgcp command: %d, port = %d, llPort = %d, OperStepIndex = %d\n\r", cmd, port, llPort, portInfo->mgcfOperStepIndex);
        mgc_log_procedure(portInfo->mgcfChnl.mgNo, portIndex, chnlIndex, tmpStr);
        
        //if (cmd == MGCP_CMD_CRCX)
            //mgcChnl[chnlIndex].status = MGC_CHNL_STATUS_CREATING;
        
        portInfo->llPort = llPort;
        portInfo->mgcfTimer = MGC_MGCF_TIMER_20S;
        portInfo->mgcfState2 = 1;
        break;
    case 1:
        if (portInfo->llCmd != 0)
        {
            res = portInfo->llCmd;
            portInfo->llCmd = 0;
            
            if ((res >= 100) && (res < 200))
                return 0;
            
            if (MGC_MG_TYPE_ANN == mgAttr->mgType)
            {
//              sapIndex = mgcMgInfo[portInfo->mgcfChnl.mgNo].sapIndex;
                sapIndex = mgcChnl[chnlIndex].sapIndex;
            }
            else
            {           
                sapIndex = mgcPhyPort[portIndex].sapIndex;
            }           
            
            cmd = portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].cmd; 
            
            sprintf(tmpStr, "mgc_mgcf_request: got response: %d, port = %d, usrPort = %d\n\r", res, port, portInfo->usrPort);
            mgc_log_procedure(portInfo->mgcfChnl.mgNo, portIndex, chnlIndex, tmpStr);
            
            if ((res == 200) ||
                ((res == 250) && (cmd == MGCP_CMD_DLCX)))
            {
                if (cmd == MGCP_CMD_AUEP)
                {   // AUEP
                    mgcMgInfo[portInfo->mgcfChnl.mgNo].stLast = 1;
                    
                    if ((mgc_is_non_virtual_mg(mgcMgInfo[portInfo->mgcfChnl.mgNo].mgAttr.mgType)) 
						&& (mgcMgInfo[portInfo->mgcfChnl.mgNo].mgAttr.mgType != MGC_MG_TYPE_AudioCoder))//revise by Francis 0822
                    {
                        for (i = 0; i < MGC_MAX_PHY_PORT_PER_MG; i++)
                        {
                            portIndex = mgcMgInfo[portInfo->mgcfChnl.mgNo].portIndex[i];
                            if (portIndex != 0xFFFF)
                            {
                                mgcPhyPort[portIndex].stLast = 1;
                            }
                        }
                    }                   
                    
                    mgcChnl[chnlIndex].auepSt = MGC_CHNL_AUEP_IDLE;
                    *clrFlag  = 0;
                    return 2;
                }
                else
                {
                    if (cmd == MGCP_CMD_CRCX)
                    {
                        if ((MGC_MG_TYPE_ANN == mgAttr->mgType) 
                            || (MGC_MG_TYPE_INTERNAL == mgAttr->mgType))
                        {
                            chnlIndex = mgcMgInfo[portInfo->mgcfChnl.mgNo].chnlStartIndex + portInfo->mgcfChnl.chlNo;   
                        }
                        else
                        {                       
                            chnlIndex = mgcPhyPort[portIndex].chnlStartIndex + portInfo->mgcfChnl.chlNo;
                        }
                        
                        mgcChnl[chnlIndex].connectNum++;
                        
//                        if ((portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex-1].flag & 0x01) == 1)
//                        {
//                          mgcConnectInfo[connectIndex].assigned = 1;
//                        }
                        mgcConnectInfo[connectIndex].status = MGC_CONNECT_STATUS_CREATED;
                    }
                    
                    if (cmd == MGCP_CMD_DLCX)
                    {
                        if ((MGC_MG_TYPE_ANN == mgAttr->mgType) 
                            || (MGC_MG_TYPE_INTERNAL == mgAttr->mgType))
                        {
                            chnlIndex = mgcMgInfo[portInfo->mgcfChnl.mgNo].chnlStartIndex + portInfo->mgcfChnl.chlNo;

                            if ((portInfo->mgcfOperId == MGC_OPER_ID_CONNECT_TONE) || (portInfo->mgcfOperId == MGC_OPER_ID_CONNECT_AAS))

                            {

                                aasOrgChnl = portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].remChnl;



                                if ((MGC_MG_TYPE_ANN == mgcMgInfo[aasOrgChnl.mgNo].mgAttr.mgType) 

                                    || (MGC_MG_TYPE_INTERNAL == mgcMgInfo[aasOrgChnl.mgNo].mgAttr.mgType))

                                {

                                    aasChnlIndexOrg = mgcMgInfo[aasOrgChnl.mgNo].chnlStartIndex + aasOrgChnl.chlNo;

                                }

                                else

                                {   

                                    aasPhyPortOrg = mgcMgInfo[aasOrgChnl.mgNo].portIndex[aasOrgChnl.portNo];

                                    aasChnlIndexOrg = mgcPhyPort[aasPhyPortOrg].chnlStartIndex + aasOrgChnl.chlNo;

                                }

    

                                if (((mgcMgInfo[aasOrgChnl.mgNo].mgAttr.mgType != MGC_MG_TYPE_INTERNAL) && (mgcMgInfo[aasOrgChnl.mgNo].mgAttr.mgType != MGC_MG_TYPE_ANN) && (aasPhyPortOrg < MGC_MAX_NUM_OF_PHY_PORT) && (aasChnlIndexOrg < MGC_MAX_NUM_OF_CHNL)) 

                                    || ((mgcMgInfo[aasOrgChnl.mgNo].mgAttr.mgType == MGC_MG_TYPE_INTERNAL) && (mgcMgInfo[aasOrgChnl.mgNo].mgAttr.mgType == MGC_MG_TYPE_ANN) && (aasChnlIndexOrg < MGC_MAX_NUM_OF_CHNL)))

                                {

                                        if ((aasOrgConnectIndex = mgcChnl[aasChnlIndexOrg].connectIndex[aasOrgChnl.connectNo]) < MGC_MAX_NUM_OF_CON)

                                        {

                                            mgcConnectInfo[aasOrgConnectIndex].aasChnl.mgNo = 0xFFFF;

                                            mgcConnectInfo[aasOrgConnectIndex].aasChnl.portNo = 0xFF;

                                            mgcConnectInfo[aasOrgConnectIndex].aasChnl.chlNo = 0xFFFF;

                                            mgcConnectInfo[aasOrgConnectIndex].aasChnl.connectNo = 0xFFFF;

                                            mgcConnectInfo[aasOrgConnectIndex].status = MGC_CONNECT_STATUS_CREATED;

                                            sprintf(tmpStr, "mgc_mgcf_request: clear aas orgconnect info: mgNo = %d, port = %d, chl = %d\n\r", aasOrgChnl.mgNo, aasOrgChnl.portNo, aasOrgChnl.chlNo);

                                            mgc_log_procedure(aasOrgChnl.mgNo, aasPhyPortOrg, aasChnlIndexOrg, tmpStr);



                                        }



                                }

                            }
                        }
                        else
                        {   
                            chnlIndex = mgcPhyPort[portIndex].chnlStartIndex + portInfo->mgcfChnl.chlNo;
                        }
                        
                        mgcChnl[chnlIndex].connectNum--;
                        
                        if ((portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].flag & 0x01) != 1)
                        {
                            mgcConnectInfo[connectIndex].assigned = 0;
                        }
                        
                        mgcConnectInfo[connectIndex].status = MGC_CONNECT_STATUS_IDLE;                          
                    }                   
                    
                    
					if((cmd == MGCP_CMD_RQNT)&&(portInfo->mgcfOperId == MGC_OPER_ID_CONNECT_TONE))
					{
					    if(portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].pkgSignal != 0)
					    {
					        mgcConnectInfo[connectIndex].status = MGC_CONNECT_STATUS_TONE;
					    }
						else
						{
					        mgcConnectInfo[connectIndex].status = MGC_CONNECT_STATUS_CREATED;						
						}
					}

					if((cmd == MGCP_CMD_CRCX)&&(portInfo->mgcfOperId == MGC_OPER_ID_CONNECT_TONE))
					{
					    MG_INFO *pMgInfo , *pRemMgInfo;						
						int		remConnIndex = -1;
						int remChnlIndex = -1;
						WORD remPortIndex;
						CHNL remChnl;

						if(portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].localChnl.mgNo < MGC_MAX_NUM_OF_MG)
						{
						    pMgInfo = &mgcMgInfo[portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].localChnl.mgNo];

							if(pMgInfo->mgAttr.mgType == MGC_MG_TYPE_ANN)
							{
							   remChnl = portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].remChnl;

							   if(remChnl.mgNo < MGC_MAX_NUM_OF_MG)
							   {
							       pRemMgInfo = &mgcMgInfo[remChnl.mgNo];
								       
                                   if ((MGC_MG_TYPE_ANN == pRemMgInfo->mgAttr.mgType)||(MGC_MG_TYPE_INTERNAL == pRemMgInfo->mgAttr.mgType))
                                   {
                                       remChnlIndex = pRemMgInfo->chnlStartIndex + remChnl.chlNo;   
                                   }
								   else
								   {
								   
								       remPortIndex = pRemMgInfo->portIndex[remChnl.portNo];
									   if ((remPortIndex < MGC_MAX_NUM_OF_PHY_PORT)&&(remChnl.chlNo < MGC_MAX_NUM_OF_CHNL))
									       remChnlIndex = mgcPhyPort[remPortIndex].chnlStartIndex+remChnl.chlNo;
								   }

								   if((remChnlIndex >= 0)&&(remChnl.connectNo < MGC_MAX_NUM_OF_CHNL_CON))
								   {
								       remConnIndex = mgcChnl[remChnlIndex].connectIndex[remChnl.connectNo];
								   }

								   if((remConnIndex >=0)&&(remConnIndex < MGC_MAX_NUM_OF_CON))
								   {
								       mgcConnectInfo[remConnIndex].status = MGC_CONNECT_STATUS_TONE;
								   }
							   }
							}
						}						
					}
               

					
                    if ((portInfo->mgcfOperStepIndex + 1) >= portInfo->mgcfOperStepsNum)
                    {
                        if (mgcSap[sapIndex].mgc_cnf == NULL)
                        {
                            *clrFlag  = 1;//    
                            return 2;
                        }

                        mgcSap[sapIndex].mgc_cnf(portInfo->usrPort, port, portInfo->mgcfOperId, MGC_OPER_SUCCESS, 0);
                        
                        if (0 == portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].delay)
                            *clrFlag  = 1;//
                        
                        return 1;
                    }
                }
            }
            else if ((MGCP_CMD_CRCX == cmd) && (502 == res))
            {
                for (i = portInfo->mgcfOperStepsNum; i > portInfo->mgcfOperStepIndex; i--)
                {
                    portInfo->mgcfOperSteps[i] = portInfo->mgcfOperSteps[i-1];
                }
                
                
                portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].cmd = MGCP_CMD_DLCX;
                portInfo->mgcfOperStepsNum = portInfo->mgcfOperStepsNum + 1;
                
                portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].flag |= 0x01;
                portInfo->mgcfState2 = 0;
                *mgcInsert = 1;
                *clrFlag  = 1;
                return 1;
            }//add by Franics 0823
            else if (cmd != MGCP_CMD_AUEP)
            {
                if (mgcSap[sapIndex].mgc_cnf != NULL)
                    mgcSap[sapIndex].mgc_cnf(portInfo->usrPort, port, portInfo->mgcfOperId, MGC_OPER_FAILURE, cmd);

                if (connectIndex < MGC_MAX_NUM_OF_CON)
                {
                    mgc_connect_init(connectIndex);
                }
                
                *clrFlag = 1;
                return 2;
            }
            else
            {   // AUEP
                *clrFlag = 0;
                mgcChnl[chnlIndex].auepSt = MGC_CHNL_AUEP_IDLE;
                return 2;
            }
            
            if (portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].delay == 0)
            {
                portInfo->mgcfState2 = 0;
                *clrFlag  = 1;
                return 1;
            }
            else
            {
                portInfo->mgcfTimer = portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].delay;
                portInfo->mgcfState2 = 2;
            }
        }
        else if (portInfo->mgcfTimer > 0)
        {
            if (--portInfo->mgcfTimer == 0)
            {
                sprintf(tmpStr, "mgc_mgcf_request: timeout, port = %d, usrPort = %d\n\r", port, portInfo->usrPort);
                mgc_log_procedure(portInfo->mgcfChnl.mgNo, portIndex, chnlIndex, tmpStr);

                if (MGC_MG_TYPE_ANN == mgAttr->mgType)
                {
                    sapIndex = mgcChnl[chnlIndex].sapIndex;
                }
                else
                {           
                    sapIndex = mgcPhyPort[portIndex].sapIndex;
                }

                cmd = portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].cmd;

                if ((cmd != MGCP_CMD_AUEP) && (MGCP_CMD_RQNT != cmd) && (MGCP_CMD_RSIP != cmd))
                {
//                  if (cmd == MGCP_CMD_DLCX)
//                  {
                        if ((MGC_MG_TYPE_ANN == mgAttr->mgType) 
                            || (MGC_MG_TYPE_INTERNAL == mgAttr->mgType))
                        {
                            chnlIndex = mgcMgInfo[portInfo->mgcfChnl.mgNo].chnlStartIndex + portInfo->mgcfChnl.chlNo;   
                        }
                        else
                        {   
                            chnlIndex = mgcPhyPort[portIndex].chnlStartIndex + portInfo->mgcfChnl.chlNo;
                        }
                        
                        mgcChnl[chnlIndex].connectNum--;
                        mgcConnectInfo[connectIndex].assigned = 0;
                        mgcConnectInfo[connectIndex].status = MGC_CONNECT_STATUS_IDLE;                      
//                  }           
                    
                    if (mgcSap[sapIndex].mgc_cnf != NULL)
                        mgcSap[sapIndex].mgc_cnf(portInfo->usrPort, port, portInfo->mgcfOperId, MGC_OPER_FAILURE, MGCP_RET_CODE_TRANS_TIME_OUT);
                    *clrFlag = 1;
                }
                else    // AUEP
                {
                    *clrFlag = 0;
                    mgcChnl[chnlIndex].auepSt = MGC_CHNL_AUEP_IDLE;
                }
                return 2;
            }
        }
        break;
    case 2:
        if (MGC_MG_TYPE_ANN == mgAttr->mgType)
        {
            sapIndex = mgcChnl[chnlIndex].sapIndex;
        }
        else
        {           
            sapIndex = mgcPhyPort[portIndex].sapIndex;
        }
        
        if (portInfo->mngCmd != MGC_MNG_CMD_IDLE)
        {
            if (portInfo->mngCmd == MGC_MNG_CMD_OVERWRITE)
            {
                if ((0 != portInfo->mgcfOperSteps[portInfo->mgcfOperStepIndex].pkgSignal)
                    || (portInfo->mgcfOperId = MGC_OPER_ID_CONNECT_TONE) 
                    || (portInfo->mgcfOperId = MGC_OPER_ID_CONNECT_AAS))
                {
                    portInfo->mgcfState2 = 0;
                    
                        *clrFlag  = 1;//    
                    
                    return 1;
                }
                else
                {
                    *clrFlag  = 1;//        
                    return 2;
                }
            }
            else if (portInfo->mngCmd == MGC_MNG_CMD_CLEAR_AFTER_OPER)
            {
                if ((MGC_MG_TYPE_ANN == mgAttr->mgType) 
                    || (MGC_MG_TYPE_INTERNAL == mgAttr->mgType))
                {
                    chnlIndex = mgcMgInfo[portInfo->mgcfChnl.mgNo].chnlStartIndex + portInfo->mgcfChnl.chlNo;   
                }
                else
                {   
                    chnlIndex = mgcPhyPort[portIndex].chnlStartIndex + portInfo->mgcfChnl.chlNo;
                }

                mgcChnl[chnlIndex].connectNum--;
                mgcConnectInfo[connectIndex].assigned = 0;
                mgcConnectInfo[connectIndex].status = MGC_CONNECT_STATUS_IDLE;
                
                if (mgcSap[sapIndex].mgc_cnf != NULL)
                {
                    if (MGC_OPER_ID_CONNECT_AAS == portInfo->mgcfOperId)
                    {
                        toneNo = (portInfo->mgcfChnl.chlNo%10) + 7;
                        mgcSap[sapIndex].mgc_cnf(portInfo->usrPort, port, portInfo->mgcfOperId, MGC_OPER_SUCCESS, toneNo);
                    }
                    else
                    {
                        mgcSap[sapIndex].mgc_cnf(portInfo->usrPort, port, portInfo->mgcfOperId, MGC_OPER_SUCCESS, 0);
                    }
                }
                
                *clrFlag  = 1;//
                return 2;
            }           
        }
        else if (portInfo->mgcfTimer > 0)
        {
            if (--portInfo->mgcfTimer == 0)
            {
                    *clrFlag  = 1;//    
                
                portInfo->mgcfState2 = 0;
                
                return 1;
            }
        }
        break;
    }
    
    return 0;
}

BYTE mgc_mgcf_indication(WORD port)
{
    PORT_INFO   *portInfo;
    MG_ATTR     *mgAttr;
    BYTE        sapIndex;
    WORD        portIndex;
    WORD        chnlIndex;
    WORD        cmd, res;
    char        tmpStr[128];
    int         connectIndex;   
    
    if (port >= MGC_MAX_NUM_OF_PORT)
    {
        return 0;
    }//add by Francis   
    
    portInfo = &mgcPort[port];
    mgAttr = &mgcMgInfo[portInfo->mgcfChnl.mgNo].mgAttr;
    
    if ((mgAttr->mgType == MGC_MG_TYPE_ANN) 
        || (mgAttr->mgType == MGC_MG_TYPE_INTERNAL))
    {
      chnlIndex = mgcMgInfo[portInfo->mgcfChnl.mgNo].chnlStartIndex + portInfo->mgcfChnl.chlNo; 
    }
    else
    {       
      portIndex = mgcMgInfo[portInfo->mgcfChnl.mgNo].portIndex[portInfo->mgcfChnl.portNo];

      if (portIndex >= MGC_MAX_NUM_OF_PHY_PORT)
      {
            mgc_log_err("mgc_mgcf_indication: invalid portIndex!\n\r");
            return -1;        
      }   
      
      chnlIndex = mgcPhyPort[portIndex].chnlStartIndex + portInfo->mgcfChnl.chlNo;
    }

    if (((portInfo->llCmd != MGCP_CMD_RSIP) && (chnlIndex >= MGC_MAX_NUM_OF_CHNL)) || (portInfo->mgcfChnl.connectNo >= MGC_MAX_NUM_OF_CHNL_CON))
        return -1;
    
    if ((portInfo->llCmd != MGCP_CMD_RQNT) && (portInfo->llCmd != MGCP_CMD_AUEP) 
        && (portInfo->llCmd != MGCP_CMD_RSIP)&& (portInfo->llCmd != MGCP_CMD_NTFY))
    {
        if ((connectIndex = mgcChnl[chnlIndex].connectIndex[portInfo->mgcfChnl.connectNo]) >= MGC_MAX_NUM_OF_CON)
        {
            mgc_log_err("mgc_mgcf_indication: invalid connectIndex!\n\r");
            return -1;
        }           
    }
    
    switch (portInfo->mgcfState2)
    {
    case 0:
        cmd = portInfo->llCmd;
        
        if (MGC_MG_TYPE_ANN == mgAttr->mgType)
        {
//          sapIndex = mgcMgInfo[portInfo->mgcfChnl.mgNo].sapIndex;
            sapIndex = mgcChnl[chnlIndex].sapIndex;
        }
        else
        {       
            sapIndex = mgcPhyPort[portIndex].sapIndex;
        }       
        
        sprintf(tmpStr, "mgc_mgcf_indication: send mgcp indication: %d, port = %d, mgNo: %d, portNo: %d, chlNo: %d\n\r",
                        cmd, port, portInfo->mgcfChnl.mgNo, portInfo->mgcfChnl.portNo, portInfo->mgcfChnl.chlNo);
        mgc_log_procedure(portInfo->mgcfChnl.mgNo, portIndex, chnlIndex, tmpStr);
        
        if (mgcSap[sapIndex].mgc_ind == NULL)
        {
            if ((portInfo->llCmd != MGCP_CMD_RQNT) && (portInfo->llCmd != MGCP_CMD_AUEP) 
                && (portInfo->llCmd != MGCP_CMD_RSIP) && (portInfo->llCmd != MGCP_CMD_NTFY))
            {
                mgcConnectInfo[connectIndex].assigned = 0;
            }
            
            return 1;
        }
        
        if ((cmd != MGCP_CMD_CRCX) && (portInfo->llCmd != MGCP_CMD_RQNT) && (portInfo->llCmd != MGCP_CMD_AUEP)
            && (cmd != MGCP_CMD_RSIP) && (mgcSap[sapIndex].usrType == MGC_USER_TYPE_MG))
        {
            portInfo->usrPort = ((strtoll(mgcConnectInfo[connectIndex].mediaAttr.conId, NULL, 16))>>32) & 0xFFFF ;
        }
        
        if ((cmd == MGCP_CMD_RSIP) || (cmd == MGCP_CMD_AUEP) || (cmd == MGCP_CMD_RQNT))
        {
            if (mgcSap[sapIndex].mgc_ind(portInfo->mgcfChnl, cmd, &portInfo->usrPort, port, NULL) < 0)
                return 1;
        }
        else if ((MGC_USER_TYPE_MGC == mgcMgInfo[portInfo->mgcfChnl.mgNo].usrType) 
                    && ((MGCP_CMD_CRCX == cmd) || (MGCP_CMD_MDCX == cmd)))
        {
            mgc_log_err("mgc_mgcf_indication: invalid command!\n\r");
            return -1;            
        }
		else if((MGC_USER_TYPE_MGC == mgcMgInfo[portInfo->mgcfChnl.mgNo].usrType)&&(MGCP_CMD_NTFY == cmd))
		{
            mgcSap[sapIndex].mgc_ind(portInfo->mgcfChnl, cmd, &portInfo->usrPort, port, &mgcChnl[chnlIndex].comMediaAttr);         		
		}
        else if (mgcSap[sapIndex].mgc_ind(portInfo->mgcfChnl, cmd, &portInfo->usrPort, port, &mgcConnectInfo[connectIndex].mediaAttr) < 0)
        {
            if ((portInfo->llCmd != MGCP_CMD_RQNT) && (portInfo->llCmd != MGCP_CMD_AUEP) 
                && (portInfo->llCmd != MGCP_CMD_RSIP))
            {
                mgcConnectInfo[connectIndex].assigned = 0;
            }
            
            return 1;
        }
        
        portInfo->mgcfTimer = MGC_MGCF_TIMER_20S;
        portInfo->mgcfState2 = 1;
        break;
    case 1:
        if (portInfo->usrCmd != 0)
        {
            res = portInfo->usrCmd;
            portInfo->usrCmd = 0;
            
            mgc_create_para(MGCP_RESPONSE, port, mgAttr, portInfo->llCmd);
            MGCP_rsp(mgcMgcpSapIndex, portInfo->llCmd, port, portInfo->llPort, res, &mgcMgcpPara);
            
            if (MGCP_CMD_CRCX == portInfo->llCmd)
            {
                if (200 == res)
                {
                    mgcConnectInfo[connectIndex].status = MGC_CONNECT_STATUS_CREATED;
                }
                else
                {
                    mgcConnectInfo[connectIndex].assigned = 0;
                    mgcConnectInfo[connectIndex].status = MGC_CONNECT_STATUS_IDLE;                    
                }
            }
            else if (MGCP_CMD_DLCX == portInfo->llCmd)
            {
                mgcConnectInfo[connectIndex].assigned = 0;
                mgcConnectInfo[connectIndex].status = MGC_CONNECT_STATUS_IDLE;
            }
            
            sprintf(tmpStr, "mgc_mgcf_indication: send mgcp response: %d, port = %d, llPort = %d\n\r", res, port, portInfo->llPort);
            mgc_log_procedure(portInfo->mgcfChnl.mgNo, portIndex, chnlIndex, tmpStr);
            
            return 1;
        }
        else if (portInfo->mgcfTimer > 0)
        {
            if (--portInfo->mgcfTimer == 0)
            {
                sprintf(tmpStr, "mgc_mgcf_indication: timeout, port = %d\n\r", port);
                mgc_log_err(tmpStr);
                
                MGCP_rsp(mgcMgcpSapIndex, portInfo->llCmd, port, portInfo->llPort, MGCP_RET_CODE_TRANS_TIME_OUT, &mgcMgcpPara);
                
                if ((portInfo->llCmd != MGCP_CMD_RQNT) && (portInfo->llCmd != MGCP_CMD_AUEP) 
                && (portInfo->llCmd != MGCP_CMD_RSIP) && (portInfo->llCmd != MGCP_CMD_NTFY))
                {
                    mgcConnectInfo[connectIndex].assigned = 0;
                    mgcConnectInfo[connectIndex].status = MGC_CONNECT_STATUS_IDLE;
                }
                
                sprintf(tmpStr, "mgc_mgcf_indication: send mgcp response: %d, port = %d, llPort = %d\n\r", MGCP_RET_CODE_TRANS_TIME_OUT, port, portInfo->llPort);
                mgc_log_procedure(portInfo->mgcfChnl.mgNo, portIndex, chnlIndex, tmpStr);
                
                return 1;
            }
        }
        break;
    }
    
    return 0;
}

void mgc_fsm(WORD port)
{
    BYTE    clrFlag;
    BYTE    mgcInsert = 0; 
    
    switch (mgcPort[port].mgcfState)
    {
    case MGC_MGCF_STATE_REQUEST:
        if (0 == mgcPort[port].mgcfOperStepIndex)
            mgcPort[port].mgcfChnl = mgcPort[port].mgcfOperSteps[0].localChnl;
        
        switch (mgc_mgcf_request(port, &clrFlag, &mgcInsert))
        {
        case 0:
            break;
        case 1:
            if (clrFlag == 1)
                mgc_update_connect_media_by_step(port, MGC_CHNL_CLEAR_PORT, mgcPort[port].mgcfChnl, NULL);
            
            if (++mgcPort[port].mgcfOperStepIndex >= mgcPort[port].mgcfOperStepsNum)
            {
                mgcPort[port].mgcfState = MGC_MGCF_STATE_INIT;
            }
            else
            {
                if (1 == mgcInsert)
                {
                    mgcPort[port].mgcfOperStepIndex--;
                    mgcInsert = 0;                     
                }
                    
                mgcPort[port].mgcfChnl = mgcPort[port].mgcfOperSteps[mgcPort[port].mgcfOperStepIndex].localChnl;                    
                mgc_fsm(port);
            }
            break;
        default:
            if (clrFlag == 1)
                mgc_update_connect_media_by_step(port, MGC_CHNL_CLEAR_PORT, mgcPort[port].mgcfChnl, NULL);
                
            mgcPort[port].mgcfState = MGC_MGCF_STATE_INIT;
            break;
        }
        break;
    case MGC_MGCF_STATE_INDICATION:
        switch (mgc_mgcf_indication(port))
        {
          case 0:
              break;
          default:
              mgcPort[port].mgcfState = MGC_MGCF_STATE_INIT;
              break;
        }
        break;
    case MGC_MGCF_STATE_INIT:
        mgc_port_init(port);
        break;
    }
}
