/****************************************************************/
/*  MGCP Implementation Program                                 */
/*  Version 9.0.1                                               */
/*  Designed By Ying Min                                        */
/*  Last Update: 2007-3-26                                      */
/****************************************************************/

#include "./include/mgcp_pub.h"
#include "./include/mgcp.h"
#include "./include/mgcp_const.h"
#include "./include/mgcp_def.h"
#include "./include/mgcp_struct.h"
#include "./include/mgcp_msg.h"
#include "./include/mgcp_trans.h"
#include "./include/mgcp_debug.h"

void mgcp_init(void)
{                     
  printf("MGCP Init Start!\n");  
    
    memset((BYTE *) &mgcpSap[0], 0, sizeof(MGCP_SAP) * MGCP_MAX_NUM_OF_SAP);
    memset((BYTE *) &mgcpPort[0], 0, sizeof(MGCP_PORT) * MGCP_MAX_NUM_OF_PORT);
    memset((BYTE *) &mgcpTransStart[0], 0, sizeof(WORD) * MGCP_MAX_NUM_OF_PORT);
    
    mgcpPortSelect = 1;
    
    mgcp_debug_set();
    
    printf("MGCP Init Complete!\n");
}

// Called every 10 ms
void mgcp_t10ms()
{
    static DWORD cnt_10ms = 0;
    
    if (!(++cnt_10ms % 10))
    {   // 100 ms
        mgcp_mon();
    }
}

void mgcp_timer(void)
{
    mgcp_recv_msg();
    mgcp_trans_proc();
    
    mgcp_t10ms();
}

int mgcp_sap_init(BYTE sapIndex)
{
    if (sapIndex >= MGCP_MAX_NUM_OF_SAP)
        return -1;
    
    memset((BYTE *) &mgcpSap[sapIndex], 0, sizeof(MGCP_SAP));
    
    return 0;
}

int mgcp_port_init(WORD port)
{
    if(port >= MGCP_MAX_NUM_OF_PORT)
        return -1;
        
    memset((BYTE *) &mgcpPort[port], 0, sizeof(MGCP_PORT));
    
    return 0;
}

int mgcp_bind(MGCP_SAP *sap)
{
    if ((sap == NULL) ||
        (sap->MGCP_ind == NULL) ||
        (sap->MGCP_cnf == NULL))
        return -1;
    
    if ((mgcpSap[0].MGCP_ind != NULL) ||
        (mgcpSap[0].MGCP_cnf != NULL))
        return -1;
    
    memcpy((BYTE *) &mgcpSap[0], sap, sizeof(MGCP_SAP));
    mgcpSap[0].name[MGCP_MAX_USER_NAME_LEN - 1] = '\0';
    
    return 0;
}

int mgcp_unbind(MGCP_SAP *sap, BYTE sapIndex)
{
    if ((sap == NULL) || (sapIndex >= MGCP_MAX_NUM_OF_SAP))
        return -1;
    
    if (strcmp(sap->name, mgcpSap[sapIndex].name) != 0)
        return -1;
    
    if (mgcp_sap_init(sapIndex) < 0)
        return -1;
    
    return 0;
}

int mgcp_get_port()
{
    WORD    port = mgcpPortSelect;
    WORD    i;

    if ((port >= MGCP_MAX_NUM_OF_PORT) || (port == 0))
    {
        if ((mgcpMonitorFg & MONITOR_ERROR) == MONITOR_ERROR)
        {
            sprintf(mgcpAsciTempBuf, "mgcpPortSelect may be changed\n port=%d\n", port);
            mgcp_log_err(mgcpAsciTempBuf);
        }

        port = 1;
    }

    for (i = 1; i < MGCP_MAX_NUM_OF_PORT; i++)
    {
        if (mgcpPort[port].flag == 1)
        {
            if (++port >= MGCP_MAX_NUM_OF_PORT)
                port = 1;
            continue;
        }
        mgcpPort[port].flag = 1;
        mgcpPortSelect = port + 1;
        if (mgcpPortSelect >= MGCP_MAX_NUM_OF_PORT)
            mgcpPortSelect = 1;
        return port;
    }
    
    return -1;
}

int MGCP_req(BYTE sapIndex, BYTE cmd, WORD usrPort, MGCP_PARA *para)
{
    int port;
    
    if ((sapIndex >= MGCP_MAX_NUM_OF_SAP) ||
        (cmd < MGCP_CMD_CRCX) || 
        (cmd > MGCP_CMD_RSIP) ||
        (para == NULL))
        return -1;
    
    if ((port = mgcp_get_port()) < 0)
        return -1;
    
    mgcpPort[port].sapIndex = sapIndex;
    mgcpPort[port].usrPort = usrPort;
    mgcpPort[port].cmd = cmd;
    mgcpPort[port].reqInd = MGCP_REQUEST;
    
    memcpy((BYTE *) &mgcpPort[port].para, para, sizeof(MGCP_PARA));
    
    return port;
}

int MGCP_cancel_req(BYTE sapIndex, BYTE cmd, WORD usrPort, WORD hdlPort)
{
    MGCP_PORT   *trans;
    
    if ((sapIndex >= MGCP_MAX_NUM_OF_SAP) ||
        (cmd < MGCP_CMD_CRCX) || 
        (cmd > MGCP_CMD_RSIP) ||
        (hdlPort >= MGCP_MAX_NUM_OF_PORT) ||
        (hdlPort == 0))
        return -1;
    
    trans = &mgcpPort[hdlPort];
    if ((trans->cmd != cmd) ||
        (trans->reqInd != MGCP_REQUEST))
        return -1;
    
    trans->cmd = 0;
    
    return 0;
}

int MGCP_rsp(BYTE sapIndex, BYTE cmd, WORD usrPort, WORD hdlPort, WORD retCode, MGCP_PARA *para)
{
    if ((sapIndex >= MGCP_MAX_NUM_OF_SAP) ||
        (cmd < MGCP_CMD_CRCX) || 
        (cmd > MGCP_CMD_RSIP) ||
        (para == NULL) ||
        (hdlPort >= MGCP_MAX_NUM_OF_PORT) ||
        (hdlPort == 0))
        return -1;
            
    memcpy((BYTE *) &mgcpPort[hdlPort].para, para, sizeof(MGCP_PARA));

  if ((retCode >=200) && (retCode < 300))
  { 
        mgcpPort[hdlPort].para.sl.retCode = retCode;
        strcpy(mgcpPort[hdlPort].para.sl.desc, mgcpRetCode[MGCP_RET_CODE_TRANS_OK_INDEX].desc);
  }
  else if ((retCode >=100) && (retCode < 200))
  { 
        mgcpPort[hdlPort].para.sl.retCode = retCode;
        strcpy(mgcpPort[hdlPort].para.sl.desc, mgcpRetCode[MGCP_RET_CODE_TEMP_RSP_INDEX].desc);
  }
  else
  {
        mgcpPort[hdlPort].para.sl.retCode = retCode;
        switch(retCode)
        {
        case MGCP_RET_CODE_TRANS_TIME_OUT:
            strcpy(mgcpPort[hdlPort].para.sl.desc, mgcpRetCode[MGCP_RET_CODE_TRANS_TIME_OUT_INDEX].desc);
        
        case MGCP_RET_CODE_INTERNAL_OVERLOAD:
            strcpy(mgcpPort[hdlPort].para.sl.desc, mgcpRetCode[MGCP_RET_CODE_TRANS_TIME_OUT_INDEX].desc);
        
        case MGCP_RET_CODE_UNEP:
            strcpy(mgcpPort[hdlPort].para.sl.desc, mgcpRetCode[MGCP_RET_CODE_UNEP_INDEX].desc);
        
        case MGCP_RET_CODE_UNCMD:
            strcpy(mgcpPort[hdlPort].para.sl.desc, mgcpRetCode[MGCP_RET_CODE_UNCMD_INDEX].desc);
        
        case MGCP_RET_CODE_RCD_ERR:
            strcpy(mgcpPort[hdlPort].para.sl.desc, mgcpRetCode[MGCP_RET_CODE_RCD_ERR_INDEX].desc);
        
        case MGCP_RET_CODE_INCONID:
            strcpy(mgcpPort[hdlPort].para.sl.desc, mgcpRetCode[MGCP_RET_CODE_INCONID_INDEX].desc);
        
        case MGCP_RET_CODE_UNCLLID:
            strcpy(mgcpPort[hdlPort].para.sl.desc, mgcpRetCode[MGCP_RET_CODE_UNCLLID_INDEX].desc);
        
        case MGCP_RET_CODE_UNMD:
            strcpy(mgcpPort[hdlPort].para.sl.desc, mgcpRetCode[MGCP_RET_CODE_UNMD_INDEX].desc);
        
        case MGCP_RET_CODE_UNPKG:
            strcpy(mgcpPort[hdlPort].para.sl.desc, mgcpRetCode[MGCP_RET_CODE_UNPKG_INDEX].desc);
        
        case MGCP_RET_CODE_NES:
            strcpy(mgcpPort[hdlPort].para.sl.desc, mgcpRetCode[MGCP_RET_CODE_NES_INDEX].desc);
        
        case MGCP_RET_CODE_ILCO:
            strcpy(mgcpPort[hdlPort].para.sl.desc, mgcpRetCode[MGCP_RET_CODE_ILCO_INDEX].desc);
        
        case MGCP_RET_CODE_UNRM:
            strcpy(mgcpPort[hdlPort].para.sl.desc, mgcpRetCode[MGCP_RET_CODE_UNRM_INDEX].desc);                                         
        
        default:
            strcpy(mgcpPort[hdlPort].para.sl.desc, "FAILED");
        }   
  }     
    
    return 0;
}
