/****************************************************************/
/*  SIP UA Implementation Program                                                               */
/*  Version 9.0.1                                                                                      */
/*  Designed By Francis                                                                              */
/*  Last Update: 2008-5-21                                                                      */
/****************************************************************/

#include "./include/sip_ua_pub.h"
#include "./include/sip_ua_def.h"
#include "./include/sip_ua_dialog.h"
#include "./include/sip_ua_const.h"
#include "./include/sip.h"
#include "./include/sip_ext.h"
#include "./include/sip_debug.h"
#include "./include/sip_ua_msg.h"

extern void sip_ua_fsm(WORD port);

int sip_ua_get_local_ip(void)
{
    struct hostent *host;
    
    if (gethostname(sipUaHostName, 50) == -1)
    {
        printf("SIP gethostname fail!\n");
        return -1;
    }
    
    if ((host = gethostbyname(sipUaHostName)) == NULL)
    {
        printf("SIP gethostbyname fail!\n");
        return -1;
    }
    else
    {
        sprintf(sipUaDottedHostIp, "%d.%d.%d.%d", 
                (BYTE)host->h_addr_list[0][0],
                (BYTE)host->h_addr_list[0][1],
                (BYTE)host->h_addr_list[0][2],
                (BYTE)host->h_addr_list[0][3]);
        sipUaHostIp = inet_addr(sipUaDottedHostIp);             // Network byte order sipHostIp, like 0xE60012AC
        printf("sipHostName: %s, sipHostIp: %s (0x%lX)\n", sipUaHostName, sipUaDottedHostIp, sipUaHostIp);
    }
    
    return 0;
}

int sip_ua_get_port()
{
    int i;
    int port = sipUaPortSelect;

    if (port >= SIP_UA_MAX_NUM_OF_PORT)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_get_port:port select have been changed\r\n");
        sip_log_err(sipAsciTempBuf);
        port = 0;
    }

    for (i = 0; i < SIP_UA_MAX_NUM_OF_PORT; i++)
    {
        if (sipUaPort[port].flag == 1)
        {
            if (++port >= SIP_UA_MAX_NUM_OF_PORT)
                port = 0;

            continue;
        }

        sip_ua_init_port(port);

        sipUaPort[port].flag = 1;

        sipUaPortSelect = (port + 1)%SIP_UA_MAX_NUM_OF_PORT;

        return port;
    }

    return -1;
}

WORD sip_ua_match_dialog_with_req(SIP_API_STRUCT *request)
{
    WORD					i;
    BYTE					method;
    SIP_HDR_CALL_ID		*callId;
    char					*toTag;
    char					*fromTag;
    SIP_DIALOG			*sipDlgPtr;
    char					*branchRecv;

    if (request == NULL)
    {
        return SIP_UA_MAX_NUM_OF_DIALOG;
    }

    method = request->sipApiMsg.sipMsg.sipStartLine.sipMethod;
    branchRecv = request->sipApiMsg.sipMsg.sipHdrVias.vias[1].params.para[0].para.paraStr;
    callId = &request->sipApiMsg.sipMsg.sipHdrCallId;
    toTag = request->sipApiMsg.sipMsg.sipHdrTo.params.para[0].para.paraStr;
    fromTag = request->sipApiMsg.sipMsg.sipHdrFrom.params.para[0].para.paraStr;

/*    if (method == SIP_METHOD_INVITE)
        return SIP_UA_MAX_NUM_OF_DIALOG;*/

    for (i = 0; i < SIP_UA_MAX_NUM_OF_DIALOG; i++)
    {
        sipDlgPtr = &sipUaDialog[i];

        if ((sipDlgPtr->flag == 0) || (sipDlgPtr->state == SIP_UA_DIALOG_DESTROY) || (strcmp(sipDlgPtr->callId.value, callId->value) != 0) 
            || (strcmp(sipDlgPtr->remoteTag, fromTag) != 0))
            continue;

        if (method == SIP_METHOD_INVITE)
            return i;

        if (method == SIP_METHOD_CANCEL)
        {
            if ((sipDlgPtr->state < SIP_UA_DIALOG_WAIT_ACK_FOR_200) && (strcmp(sipDlgPtr->invBranch, branchRecv) == 0)) 
                return i;
            else
                continue;
        }
        else
        {
            if (strcmp(sipDlgPtr->localTag, toTag) != 0)
                continue;

            return i;
        }
    }

    return SIP_UA_MAX_NUM_OF_DIALOG;
}

WORD sip_ua_match_dialog_with_rsp(SIP_API_STRUCT *response)
{
    WORD        i;
    SIP_HDR_CALL_ID *callId;
    char        *toTag;
    char        *fromTag;

    if (response == NULL)
    {
        return SIP_UA_MAX_NUM_OF_DIALOG;
    }

    callId = &response->sipApiMsg.sipMsg.sipHdrCallId;
    toTag = response->sipApiMsg.sipMsg.sipHdrTo.params.para[0].para.paraStr;
    fromTag = response->sipApiMsg.sipMsg.sipHdrFrom.params.para[0].para.paraStr;

    for (i = 0; i < SIP_UA_MAX_NUM_OF_DIALOG; i++)
    {
        if ((sipUaDialog[i].flag == 0) 
            || (strcmp(sipUaDialog[i].callId.value, callId->value) != 0) 
            || (strcmp(sipUaDialog[i].localTag, fromTag) != 0))
            continue;

        if (sipUaDialog[i].state < SIP_UA_DIALOG_WAIT_ACK_FOR_200)
        {
            return i;
        }
        else
        {
            if (strcmp(sipUaDialog[i].remoteTag, toTag) != 0)
                continue;

            return i;
        }
    }

    return SIP_UA_MAX_NUM_OF_DIALOG;
}

int sip_ua_select_user_by_domain(SIP_API_STRUCT *sipApiMsg)
{
    int  i;
    SIP_URI      *sipUri;

    if (sipApiMsg == NULL)
        return -1;

    sipUri = &sipApiMsg->sipApiMsg.sipMsg.sipStartLine.requestUri;

    for (i = 0; i < SIP_UA_MAX_NUM_OF_SAP; i++)
    {
        if ((sipUaSaps[i].flag == 1)
            &&  (strcmp(sipUaSaps[i].sipUaSap.domain, sipUri->host.addr.domain) == 0))
            return i;
    }

    return -1;
}

int sip_ua_check_retransmit_invit(SIP_API_STRUCT *sipApiMsg)
{
    SIP_HDR_CALL_ID *callId;
    char            *fromTag;
    int             i;

    callId = &sipApiMsg->sipApiMsg.sipMsg.sipHdrCallId;
    fromTag = sipApiMsg->sipApiMsg.sipMsg.sipHdrFrom.params.para[0].para.paraStr;

    for (i = 0; i < SIP_UA_MAX_NUM_OF_PORT; i++)
    {
        if (sipUaPort[i].flag != 1)
            continue;

        if ((strcmp(sipUaPort[i].callStruct.callId.value, callId->value) == 0) 
            && (strcmp(sipUaPort[i].callStruct.callId.host, callId->host) == 0) 
            && (strcmp(sipUaPort[i].callStruct.fromTag, fromTag) == 0))
            return i;
    }
    
    return -1;
}

int sip_ua_allocate_port_for_req(BYTE method, SIP_API_STRUCT *sipApiMsg)
{
    int port;

    if (((sipApiMsg->sipApiMsg.sipMsg.sipGenHdrFlag[0] & SIP_HDR_EXPIRES_MASK) == SIP_HDR_EXPIRES_MASK) 
         && (sipApiMsg->sipApiMsg.sipMsg.sipHdrExpires.value == 0))
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_allocate_port_for_req:expier value is 0\r\n");
        sip_log_err(sipAsciTempBuf);
        return -2;
    }

    if ((port = sip_ua_get_port()) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_allocate_port_for_req:no enough resource\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    sipUaPort[port].sipuafState = SIP_UA_FSM_STATE_INDICATE;
    sipUaPort[port].mainState = SIP_UA_MAIN_STATE_IDLE;

    if ((sipApiMsg->sipApiMsg.sipMsg.sipGenHdrFlag[0] & SIP_HDR_EXPIRES_MASK) == SIP_HDR_EXPIRES_MASK)
    {
        sipUaPort[port].sipuafTimer = (sipApiMsg->sipApiMsg.sipMsg.sipHdrExpires.value * 100);
    }
    else
    {
        sipUaPort[port].sipuafTimer = SIP_UA_FSM_TIMER;
    }

    sipUaPort[port].rcvCmd = method;

    return port;
}

int sip_ua_sip_recv_proc(WORD sipPort, WORD upPort, BYTE transFlag, SIP_API_STRUCT *sipApiMsg)
{
    int              ret;
//    int              sapIndex;
    WORD             dialogId;
    BYTE             method;
    int              statusCode;
    SIP_API_STRUCT   sdSipMsg;
    int              port;
    DWORD            usrPort;
    pal_cg_struct    *cg;
    char                 *localDomain;
    char                 *destDomain;
    SIP_EVENTHANDLE_STRUCT *event_handle = NULL;

    if (sipApiMsg == NULL)
        return -1;

    localDomain = sipApiMsg->sipApiMsg.sipMsg.sipStartLine.requestUri.host.addr.domain;
    destDomain = sipApiMsg->sipApiMsg.sipMsg.sipHdrVias.vias[sipApiMsg->sipApiMsg.sipMsg.sipHdrVias.head].url.domain;

    memset(&sipUaRecvMsg, 0, sizeof(SIP_API_STRUCT));

    switch(transFlag)
    {
    case SIP_TRANSPORT_LAYER:
        if (sipApiMsg->sipApiType == SIP_API_REQ_MSG)
        {
/*            if ((sapIndex = sip_ua_select_user_by_domain(sipApiMsg)) < 0)
            {
                sprintf(sipAsciTempBuf, "sip ua recv msg can not find user\r\n");
                sip_log_err(sipAsciTempBuf);
                return -1;
            }*/

           if ((cg = (pal_cg_struct *)pal_sip_find_cg(localDomain, destDomain)) == NULL)
           {
               sprintf((char *)sipAsciTempBuf, "sip_ua_sip_recv: can not find cg!\r\n");
               sip_log_err(sipAsciTempBuf);
               return -1;
           }

            if ((dialogId = sip_ua_match_dialog_with_req(sipApiMsg)) >= SIP_UA_MAX_NUM_OF_DIALOG)
                dialogId = SIP_UA_NULL_DIALOG;

            method = sipApiMsg->sipApiMsg.sipMsg.sipStartLine.sipMethod;

            if ((method == SIP_METHOD_INVITE) && (dialogId <= SIP_UA_MAX_NUM_OF_DIALOG))
            {
                sprintf((char *)sipAsciTempBuf, "sip ua recv retransmitted invite\r\n");
                sip_log_err(sipAsciTempBuf);
                return 0;
            }

            if (((method == SIP_METHOD_RE_INVITE) || (method == SIP_METHOD_CANCEL) || (method == SIP_METHOD_ACK) || (method == SIP_METHOD_BYE) || (method == SIP_METHOD_INFO)) 
                && (dialogId == SIP_UA_NULL_DIALOG))
            {
                if (method != SIP_METHOD_ACK)
                {
                    memcpy(&sdSipMsg, sipApiMsg, sizeof(SIP_API_STRUCT));
                    sdSipMsg.sipApiType = SIP_API_RES_MSG;
                    sdSipMsg.sipApiMsg.sipMsg.sipStartLine.statusCode = 481;
                    strcpy(sdSipMsg.sipApiMsg.sipMsg.sipStartLine.reasonPhrase, "Call/Transaction Does Not Exist");
                    sdSipMsg.sipApiMsg.sipMsg.sipEntity.sipHdrContentLength = 0;
                    sdSipMsg.sipApiMsg.sipMsg.sipGenHdrFlag[0] = SIP_HDR_CALL_ID_MASK | SIP_HDR_CSEQ_MASK 
                                                                 | SIP_HDR_FROM_MASK | SIP_HDR_TO_MASK | SIP_HDR_VIA_MASK;

                    sdSipMsg.sipApiMsg.sipMsg.sipReStruct.sipReHdrFlag[0] = 0;
                    sip_send_msg(SIP_NULL_TRANS_ID, SIP_NULL_UP_PORT, SIP_TRANSPORT_LAYER, &sdSipMsg);
                }

                sprintf((char *)sipAsciTempBuf, "sip ua recv a inside msg without relational dialog\r\n");
                sip_log_err(sipAsciTempBuf);
                return -7;
            }

            if (dialogId < SIP_UA_NULL_DIALOG)
            {
                if ((method != SIP_METHOD_ACK) && (method != SIP_METHOD_CANCEL))
                {
                    if ((ret =sip_ua_update_dialog_with_req(dialogId, sipApiMsg)) < 0)
                    {
                        if (ret == -2)
                        {
                        //need forward develop
                            memset(&sdSipMsg, 0, sizeof(SIP_API_STRUCT));
                            memcpy(&sdSipMsg, sipApiMsg, sizeof(SIP_API_STRUCT));
                            sdSipMsg.sipApiType = SIP_API_RES_MSG;
                            sdSipMsg.sipApiMsg.sipMsg.sipStartLine.statusCode = 500;
                            strcpy( sdSipMsg.sipApiMsg.sipMsg.sipStartLine.reasonPhrase, "Server Internal Error");
                            sdSipMsg.sipApiMsg.sipMsg.sipEntity.sipHdrContentLength = 0;
                            sdSipMsg.sipApiMsg.sipMsg.sipGenHdrFlag[0]  = SIP_HDR_CALL_ID_MASK | SIP_HDR_CSEQ_MASK |
                                                                      SIP_HDR_FROM_MASK | SIP_HDR_TO_MASK | SIP_HDR_VIA_MASK;
                            sdSipMsg.sipApiMsg.sipMsg.sipReStruct.sipReHdrFlag[0] = 0;
                            sip_send_msg(SIP_NULL_TRANS_ID, SIP_NULL_UP_PORT, SIP_TRANSPORT_LAYER, &sdSipMsg);
                        }
                        sprintf((char *)sipAsciTempBuf, "sip_ua_sip_recv:update dialog with req failed, ret=%d\r\n", ret);
                        sip_log_err(sipAsciTempBuf);
                        return -1;
                    }
                }
                else
                {
                    if (sipApiMsg->sipApiMsg.sipMsg.sipHdrCseq.value != sipUaDialog[dialogId].remoteInvCseq)
                    {
                        sprintf((char *)sipAsciTempBuf, "sip_ua_sip_recv:ack or cancel cseq is not equal to invite\r\n");
                        sip_log_err(sipAsciTempBuf);
                        return -6;
                    }
                }
            }

            if (method != SIP_METHOD_ACK)
            {
                if (method == SIP_METHOD_INVITE)
                {
                    if (sip_ua_check_retransmit_invit(sipApiMsg) >= 0)
                    {
                        sprintf((char *)sipAsciTempBuf, "sip_ua_sip_recv:retransmit invit already in progress\r\n");
                        sip_log_err(sipAsciTempBuf);
                        return 0;
                    }
                }

                if ((port = sip_ua_allocate_port_for_req(method, sipApiMsg)) < 0)
                {
                    if (port == -2)
                    {
                        memset(&sdSipMsg, 0, sizeof(SIP_API_STRUCT));
                        memcpy(&sdSipMsg, sipApiMsg, sizeof(SIP_API_STRUCT));
                        sdSipMsg.sipApiType = SIP_API_RES_MSG;
                        sdSipMsg.sipApiMsg.sipMsg.sipStartLine.statusCode = 487;
                        strcpy(sdSipMsg.sipApiMsg.sipMsg.sipStartLine.reasonPhrase, "Request Terminated");
                        sdSipMsg.sipApiMsg.sipMsg.sipEntity.sipHdrContentLength = 0;
                        sdSipMsg.sipApiMsg.sipMsg.sipGenHdrFlag[0] = SIP_HDR_CALL_ID_MASK | SIP_HDR_CSEQ_MASK |
                                                 SIP_HDR_FROM_MASK | SIP_HDR_TO_MASK | SIP_HDR_VIA_MASK;
                        sdSipMsg.sipApiMsg.sipMsg.sipReStruct.sipReHdrFlag[0] = 0;
                        sip_send_msg(SIP_NULL_TRANS_ID, SIP_NULL_UP_PORT, SIP_TRANSPORT_LAYER, &sdSipMsg);
                    }
                    else
                    {
                        sprintf((char *)sipAsciTempBuf, "sip_ua_sip_recv:no enough resource\r\n");
                        sip_log_err(sipAsciTempBuf);
                    }
                    return -1;
                }

                if (method ==  SIP_METHOD_INVITE)
                {
                    memcpy(&sipUaPort[port].callStruct.callId, &sipApiMsg->sipApiMsg.sipMsg.sipHdrCallId, sizeof(SIP_HDR_CALL_ID));
                    strcpy(sipUaPort[port].callStruct.fromTag, sipApiMsg->sipApiMsg.sipMsg.sipHdrFrom.params.para[0].para.paraStr);

/*                    cg = pal_sip_find_cg(sipApiMsg->sipApiMsg.sipMsg.sipHdrVias.vias[sipApiMsg->sipApiMsg.sipMsg.sipHdrVias.head].url.host.addr.domain);

                    if (cg == NULL)
                    {
                        sprintf(sipAsciTempBuf, "sip_ua_sip_recv: Invite req can not find cg!\r\n");
                        sip_log_err(sipAsciTempBuf);
                        sip_ua_init_port(port);
                        return -1;
                    }*/

                    sip_ua_set_inv_temp_rsp(port, sipApiMsg);

                    usrPort = SIP_UA_NULL_UP_PORT;
                }
                else
                {
                    if (dialogId < SIP_UA_MAX_NUM_OF_DIALOG)
                    {
                        usrPort = sipUaDialog[dialogId].usrPort;
                        sipUaDialog[dialogId].sipUaPort = port;
                    }
                    else
                    {
                        usrPort = SIP_UA_NULL_UP_PORT;
                    }
//                    cg = NULL;
                }

                event_handle = (SIP_EVENTHANDLE_STRUCT *)pal_get_handler(cg->id);
                event_handle->recv_req(port, usrPort, dialogId, method, sipApiMsg, cg);
//                sipUaSaps[sapIndex].sipUaSap.recv_req(port, usrPort, dialogId, method, sipApiMsg, cg);
            }
            else
            {
                if (sipUaDialog[dialogId].uaPort >= SIP_UA_MAX_NUM_OF_PORT)
                {
                    sprintf((char *)sipAsciTempBuf, "sip_ua_sip_recv:recv ack, but no port in dialog to proc inv rsp\r\n");
                    sip_log_err(sipAsciTempBuf);
                    return -3;
                }

                sipUaPort[sipUaDialog[dialogId].uaPort].rcvCmd = SIP_METHOD_ACK;

                memcpy(&sipUaRecvMsg, sipApiMsg, sizeof(SIP_API_STRUCT));

                sip_ua_fsm(sipUaDialog[dialogId].uaPort);
            }
            
        }
        else
        {
            if ((sipApiMsg->sipApiMsg.sipMsg.sipHdrCseq.method == SIP_METHOD_INVITE) && (sipApiMsg->sipApiMsg.sipMsg.sipStartLine.statusCode == 200) 
                && ((dialogId = sip_ua_match_dialog_with_rsp(sipApiMsg)) < SIP_UA_MAX_NUM_OF_DIALOG))
            {
                if (sipUaDialog[dialogId].uaAckPort >= SIP_UA_MAX_NUM_OF_PORT)
                {
                    sprintf((char *)sipAsciTempBuf, "sip_ua_sip_recv:recv retransmitted 200, no ack proc port in dialog\r\n");
                    sip_log_err(sipAsciTempBuf);
                    return -5;
                }

                sipUaPort[sipUaDialog[dialogId].uaAckPort].rcvCmd = 200;

                memcpy(&sipUaRecvMsg, sipApiMsg, sizeof(SIP_API_STRUCT));

                sip_ua_fsm(sipUaDialog[dialogId].uaAckPort);
            }
            else
            {
                sprintf((char *)sipAsciTempBuf, "sip_ua_sip_recv:recv rsp from transport layer\r\n");
                sip_log_err(sipAsciTempBuf);
                return -4;
            }
        }

        break;
    case SIP_TRANSACTION_LAYER:
        if ((upPort >= SIP_UA_MAX_NUM_OF_PORT) || (sipUaPort[upPort].flag != 1))
        {
            return -1;
        }

        if (sipApiMsg->sipApiType == SIP_API_REQ_MSG)
        {
            sprintf((char *)sipAsciTempBuf, "sip_ua_sip_recv:recv req from transaction layer\r\n");
            sip_log_err(sipAsciTempBuf);
            return -1;
        }
        else
        {
            if ((dialogId = sip_ua_match_dialog_with_rsp(sipApiMsg)) >= SIP_UA_MAX_NUM_OF_DIALOG)
                dialogId = SIP_UA_NULL_DIALOG;

            if (sipUaPort[upPort].dialogId != dialogId)
            {
                sprintf((char *)sipAsciTempBuf, "sip_ua_sip_recv:find dialog wrong\r\n");
                sip_log_err(sipAsciTempBuf);
                dialogId = sipUaPort[upPort].dialogId;
//                return -1;
            }

            if ((dialogId < SIP_UA_MAX_NUM_OF_DIALOG) && (sipUaPort[upPort].cgId != sipUaDialog[dialogId].cgId))//sipUaPort[upPort].sapIndex != sipUaDialog[dialogId].userIndex
            {
                sprintf((char *)sipAsciTempBuf, "sip_ua_sip_recv: cg id wrong\r\n");
                sip_log_err(sipAsciTempBuf);
                return -1;
            }

            statusCode = sipApiMsg->sipApiMsg.sipMsg.sipStartLine.statusCode;

            sipUaPort[upPort].rcvCmd= statusCode;

            memcpy(&sipUaRecvMsg, sipApiMsg, sizeof(SIP_API_STRUCT));

            sip_ua_fsm(upPort);
        }
        
        break;
    default:
        return -1;
    }

    return 0;
}

int sip_ua_init_dialog(WORD dialogId)
{
    if (dialogId >= SIP_UA_MAX_NUM_OF_DIALOG)
    {
        return -1;
    }

    memset(&sipUaDialog[dialogId], 0, sizeof(SIP_DIALOG));
    sipUaDialog[dialogId].uaPort = 0xFFFF;
    sipUaDialog[dialogId].uaAckPort = 0xFFFF;

    return 0;
}

int sip_ua_init_port(WORD port)
{
    if (port >= SIP_UA_MAX_NUM_OF_PORT)
    {
        return -1;
    }

    memset(&sipUaPort[port], 0, sizeof(SIP_UA_PORT));
    sipUaPort[port].dialogId = SIP_UA_NULL_DIALOG;
    sipUaPort[port].llPort = 0xFFFF;
    sipUaPort[port].usrPort = 0xFFFF;

    return 0;
}

void sip_ua_timer()
{
    WORD port;
    
    for (port = 0; port < SIP_UA_MAX_NUM_OF_PORT; port++)
    {
        if (sipUaPort[port].flag == 0)
            continue;

        sip_ua_fsm(port);
    }
    
    sip_t10ms();
}

int sip_ua_regist_in_sip()
{
    sipUaSipUser.proxyType= SIP_PROXY_TYPE_NONE;
    strcpy(sipUaSipUser.userName, "SIP_UA");
    strcpy(sipUaSipUser.domain, sipUaDottedHostIp);
    sipUaSipUser.recv_proc = sip_ua_sip_recv_proc;

    if ((sipUaSipIndex = sip_register_user(&sipUaSipUser)) < 0)
    {
        printf("SIP UA Module register in SIP Module Failed\r\n");
        return -1;
    }

    return 0;
}

int sip_ua_init()
{
    WORD        i;

    printf("SIP UA Module Init Start!\n");

    if (sip_ua_get_local_ip() < 0)
        exit(1);

    if (sip_ua_regist_in_sip() < 0)
    {
        printf("SIP UA Module regist in sip fail\r\n");
    }

    sipUaPortSelect = 0;
    sipUaDialogSelect = 0;

    for (i = 0; i < SIP_UA_MAX_NUM_OF_DIALOG; i++)
    {
        sip_ua_init_dialog(i);
    }
    
    for (i = 0; i < SIP_UA_MAX_NUM_OF_PORT; i++)
    {
        sip_ua_init_port(i);
    }

    memset((BYTE *)&sipUaSaps[0], 0, sizeof(SIP_UA_SAPS) * SIP_UA_MAX_NUM_OF_SAP);

    memset((BYTE *)&sipUaRecvMsg, 0, sizeof(SIP_API_STRUCT));

    printf("SIP UA Module Init Complete!\n");

    return 0;
}

/*int sip_ua_bind(SIP_UA_SAP *sap)
{
    BYTE    sapIndex;

    if ((sap == NULL)  || (sap->recv_req == NULL)  || (sap->recv_resp == NULL) 
      || (sap->proxyType != SIP_PROXY_TYPE_NONE))
    {
        sprintf(sipAsciTempBuf, "sip_ua_bind:sap malformed\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    for (sapIndex = 0; sapIndex < SIP_UA_MAX_NUM_OF_SAP; sapIndex++)
    {
        if ((sipUaSaps[sapIndex].flag == 1) &&
            (strcmp(sipUaSaps[sapIndex].sipUaSap.userName, sap->userName) == 0))
        {
            memcpy(&sipUaSaps[sapIndex].sipUaSap, sap, sizeof(SIP_UA_SAP));

            if (sip_store_sip_ua_user(sapIndex, sap->domain) < 0)
            {       
                sprintf(sipAsciTempBuf, "sip_ua_bind:sip store sip ua user failed!\r\n");
                sip_log_err(sipAsciTempBuf);
            }

            return sapIndex;
        }
    }

    for (sapIndex = 0; sapIndex < SIP_UA_MAX_NUM_OF_SAP; sapIndex++)
    {
        if (sipUaSaps[sapIndex].flag != 0)
            continue;

        sipUaSaps[sapIndex].flag = 1;

        memcpy((BYTE *)&sipUaSaps[sapIndex].sipUaSap, sap, sizeof(SIP_UA_SAP));

        if (sip_store_sip_ua_user(sapIndex, sap->domain) < 0)
        {       
            sprintf(sipAsciTempBuf, "sip_ua_bind:sip store sip ua user failed\r\n");
            sip_log_err(sipAsciTempBuf);
        }

        return sapIndex;
    }

    sprintf(sipAsciTempBuf, "sip ua user bind fail\r\n");
    sip_log_err(sipAsciTempBuf);

    return -1;
}*/
