#include "./include/sip_ua_pub.h"
#include "./include/sip_ua_const.h"
#include "./include/sip_ua_struct.h"
#include "./include/sip_ua_msg.h"
#include "./include/sip_ua_ext.h"
#include "./include/sip_ua_dialog.h"
#include "./include/sip_ua.h"
#include "./include/sip_const.h"
#include "./include/sip_ext.h"
#include "./include/sip_debug.h"

extern void sip_ua_fsm(WORD port);

int sip_ua_create_register_tag(int port, SIP_GEN_PARA *tagPara)
{
    struct timeval  tv;

    if ((port < 0) || (port >= SIP_UA_MAX_NUM_OF_PORT))
        return -1;

    gettimeofday(&tv, NULL);

    tagPara->paraName = SIP_API_PNAME_TAG;
    tagPara->paraType = SIP_API_PTYPE_STRING;
    sprintf(tagPara->para.paraStr, "%X%lX%lX", port, tv.tv_sec, tv.tv_usec);

    return 0;
}

int sip_ua_create_register_call_id(WORD usrPort, SIP_HDR_CALL_ID *callId)
{
    struct timeval  tv;

    gettimeofday(&tv, NULL);

    sprintf(callId->value, "%X%lX%lX", usrPort, tv.tv_usec, tv.tv_sec);
    strcpy(callId->host, sipUaDottedHostIp);

    return 0;
}

int sip_ua_set_send_cmd(SIP_UA_PORT *sipUaPortPtr, SIP_API_STRUCT *sipApiMsg)
{
    SIP_START_LINE      *startLine;

    if ((sipUaPortPtr == NULL) || (sipApiMsg == NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip ua set send cmd failed\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    startLine = &sipApiMsg->sipApiMsg.sipMsg.sipStartLine;
    
    if (sipApiMsg->sipApiType == SIP_API_REQ_MSG)
        sipUaPortPtr->sdCmd = startLine->sipMethod;
    else if (sipApiMsg->sipApiType == SIP_API_RES_MSG)
        sipUaPortPtr->sdCmd = startLine->statusCode;
    else
        return -1;
    
    return 0;
}

void sip_ua_fill_uri_in_dialog(SIP_URI *sipUri, SIP_UA_URI *sipUaUri)
{
    if ((sipUri == NULL) || (sipUaUri == NULL))
    {
        return;
    }

    sipUri->uriType = sipUaUri->uriType;
    strcpy(sipUri->userName, sipUaUri->userName);
    strcpy(sipUri->password, sipUaUri->password);
    strcpy(sipUri->host.addr.domain, sipUaUri->domain);
}

int sip_ua_fill_tag_in_dialog(SIP_GEN_PARA *tagPara, char *tagOrg)
{
    if ((tagPara == NULL) || (tagOrg == NULL))
    {
        return 0;
    }

    if (*tagOrg != '\0')
    {
        tagPara->paraName = SIP_API_PNAME_TAG;
        tagPara->paraType = SIP_API_PTYPE_STRING;
        strcpy(tagPara->para.paraStr, tagOrg);
        return 1;
    }

    return 0;
}

int sip_ua_fill_msg_with_dialog(WORD dialogId, SIP_API_STRUCT *sdMsg)
{
    SIP_DIALOG  *sipUaDlgPtr;
    SIP_MSG     *sipMsg;
//   SIP_URI     url;

    if (sdMsg == NULL)
        return -1;

    if ((dialogId >= SIP_UA_MAX_NUM_OF_DIALOG) || (sipUaDialog[dialogId].flag == 0))
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_fill_msg_with_dialog:dialogId wrong\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    sipUaDlgPtr = &sipUaDialog[dialogId];
    sipMsg = &sdMsg->sipApiMsg.sipMsg;

    if (sdMsg->sipApiType == SIP_API_REQ_MSG)
    {
        sip_ua_fill_uri_in_dialog(&sipMsg->sipHdrFrom.url, &sipUaDlgPtr->localURI);
        if (sip_ua_fill_tag_in_dialog(&sipMsg->sipHdrFrom.params.para[0], sipUaDlgPtr->localTag) == 1)
            sipMsg->sipHdrFrom.params.paraNum++;
        sipMsg->sipGenHdrFlag[0] |= SIP_HDR_FROM_MASK;

        sip_ua_fill_uri_in_dialog(&sipMsg->sipHdrTo.url, &sipUaDlgPtr->remoteURI);
        if (sip_ua_fill_tag_in_dialog(&sipMsg->sipHdrTo.params.para[0], sipUaDlgPtr->remoteTag) == 1)
            sipMsg->sipHdrTo.params.paraNum++;
        sipMsg->sipGenHdrFlag[0] |= SIP_HDR_TO_MASK;

        memcpy(&sipMsg->sipHdrCallId, &sipUaDlgPtr->callId, sizeof(SIP_HDR_CALL_ID));
        sipMsg->sipGenHdrFlag[0] |= SIP_HDR_CALL_ID_MASK;

        if (sipMsg->sipStartLine.sipMethod != SIP_METHOD_INVITE)
        {
            if ((sipUaDlgPtr->paramFlag & SIP_UA_DIALOG_REMOTE_TARGET_FLAG) == SIP_UA_DIALOG_REMOTE_TARGET_FLAG)
            {
                sip_ua_fill_uri_in_dialog(&sipMsg->sipStartLine.requestUri, &sipUaDlgPtr->remoteTarget);
            }
        }

        if ((sipMsg->sipStartLine.sipMethod == SIP_METHOD_INVITE) || (sipMsg->sipStartLine.sipMethod == SIP_METHOD_CANCEL))
        {
            if (sipMsg->sipStartLine.sipMethod == SIP_METHOD_INVITE)
                sipUaDlgPtr->invCSeq = sipUaDlgPtr->localCseq.value= sipMsg->sipHdrCseq.value = 1;
            else
                sipMsg->sipHdrCseq.value =  sipUaDlgPtr->invCSeq;
        }
        else
        {
            if ((sipUaDlgPtr->type == SIP_CALLER) && (sipUaDlgPtr->invCSeq == 0))
            {
                sprintf((char *)sipAsciTempBuf, "sip_ua_fill_msg_with_dialog:caller send other req before sending invite\r\n");
                sip_log_err(sipAsciTempBuf);
                return -2;
            }
            
            if (sipMsg->sipStartLine.sipMethod != SIP_METHOD_ACK)
            {
                sipUaDlgPtr->localCseq.value = sipUaDlgPtr->localCseq.value + 1;
                sipMsg->sipHdrCseq.value = sipUaDlgPtr->localCseq.value;
            }
            else
            {
                sipMsg->sipHdrCseq.value =  sipUaDlgPtr->invCSeq;
            }
        }

        sipMsg->sipGenHdrFlag[0] |= SIP_HDR_CSEQ_MASK;

        if (sipUaDlgPtr->routeSets.num != 0)
        {
            memcpy(&sipMsg->sipReStruct.sipReHdr.sipReqHdr.sipHdrRoutes, (SIP_HDR_ROUTES *)&sipUaDlgPtr->routeSets, sizeof(SIP_HDR_ROUTES));

            if (sipUaDlgPtr->routeSets.recRoutes[0].url.params.para[0].paraName != SIP_API_PNAME_LR)//if (sipUaDlgPtr->routeSets.recRoutes[0].params.para[0].paraName != SIP_API_PNAME_LR)
            {
                if (sipUaDlgPtr->routeSets.num >= SIP_MAX_NUM_OF_RECORD_ROUTES)
                {
                    memcpy(&sipMsg->sipReStruct.sipReHdr.sipReqHdr.sipHdrRoutes.routes[0].url, &sipMsg->sipStartLine.requestUri, sizeof(SIP_URI));
                }
                else
                {
                    memcpy(&sipMsg->sipReStruct.sipReHdr.sipReqHdr.sipHdrRoutes.routes[sipUaDlgPtr->routeSets.num].url, &sipMsg->sipStartLine.requestUri, sizeof(SIP_URI));//0
                }

                memcpy(&sipMsg->sipStartLine.requestUri, &sipUaDlgPtr->routeSets.recRoutes[0].url, sizeof(SIP_URI));

                sipMsg->sipReStruct.sipReHdr.sipReqHdr.sipHdrRoutes.head = 1;
            }

            sdMsg->sipTransAddr.addr.ipV4 = inet_addr(sipUaDlgPtr->routeSets.recRoutes[0].url.host.addr.domain);
            if (sipUaDlgPtr->routeSets.recRoutes[0].url.port != 0)
                sdMsg->sipTransAddr.port = sipUaDlgPtr->routeSets.recRoutes[0].url.port;
            else
                sdMsg->sipTransAddr.port = 5060;
//need forward develop
            sipMsg->sipReStruct.sipReHdrFlag[0] |= SIP_HDR_ROUTE_MASK;
        }


    }
    else
    {
        sip_ua_fill_uri_in_dialog(&sipMsg->sipHdrFrom.url, &sipUaDlgPtr->remoteURI);
        if (sip_ua_fill_tag_in_dialog(&sipMsg->sipHdrFrom.params.para[0], sipUaDlgPtr->remoteTag) == 1)
            sipMsg->sipHdrFrom.params.paraNum++;
        sipMsg->sipGenHdrFlag[0] |= SIP_HDR_FROM_MASK;

        sip_ua_fill_uri_in_dialog(&sipMsg->sipHdrTo.url, &sipUaDlgPtr->localURI);
        if (sip_ua_fill_tag_in_dialog(&sipMsg->sipHdrTo.params.para[0], sipUaDlgPtr->localTag) == 1)
            sipMsg->sipHdrTo.params.paraNum++;
        sipMsg->sipGenHdrFlag[0] |= SIP_HDR_TO_MASK;

        memcpy(&sipMsg->sipHdrCallId, &sipUaDlgPtr->callId, sizeof(SIP_HDR_CALL_ID));
        sipMsg->sipGenHdrFlag[0] |= SIP_HDR_CALL_ID_MASK;

        if (sipMsg->sipHdrCseq.method == SIP_METHOD_INVITE)
        {
            sipMsg->sipHdrCseq.value = sipUaDlgPtr->remoteInvCseq;
        }
        else
        {
            sipMsg->sipHdrCseq.value = sipUaDlgPtr->remoteCseq.value;
        }
        sipMsg->sipGenHdrFlag[0] |= SIP_HDR_CSEQ_MASK;

         if ((sipUaDlgPtr->routeSets.num != 0) 
//              && ((sipUaDlgPtr->paramFlag & SIP_UA_DIALOG_RECORD_ROUTE_SEND_FLAG) != SIP_UA_DIALOG_RECORD_ROUTE_SEND_FLAG) 
              && (sipUaDlgPtr->type == SIP_CALLEE) && (sipMsg->sipHdrCseq.method == SIP_METHOD_INVITE))
         {
             memcpy(&sipMsg->sipHdrRecordRoutes, &sipUaDlgPtr->routeSets, sizeof(SIP_HDR_RECORD_ROUTES));
//             sipUaDlgPtr->paramFlag |= SIP_UA_DIALOG_RECORD_ROUTE_SEND_FLAG;
             sipMsg->sipGenHdrFlag[0] |= SIP_HDR_RECORD_ROUTE_MASK;
         }
    }

    return 0;
}

int sip_ua_update_retransmit_para(WORD dialogId, SIP_API_STRUCT *sdMsg)
{
    SIP_DIALOG  *sipUaDlgPtr;
    SIP_MSG     *sipMsg;
//   SIP_URI     url;

    if (sdMsg == NULL)
        return -1;

    if ((dialogId >= SIP_UA_MAX_NUM_OF_DIALOG) || (sipUaDialog[dialogId].flag == 0))
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_update_retransmit_para:dialogId wrong\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    sipUaDlgPtr = &sipUaDialog[dialogId];
    sipMsg = &sdMsg->sipApiMsg.sipMsg;

    if (sdMsg->sipApiType == SIP_API_REQ_MSG)
    {
        if (sipUaDlgPtr->routeSets.num != 0)
        {
            memcpy(&sipMsg->sipReStruct.sipReHdr.sipReqHdr.sipHdrRoutes, (SIP_HDR_ROUTES *)&sipUaDlgPtr->routeSets, sizeof(SIP_HDR_ROUTES));

            if (sipUaDlgPtr->routeSets.recRoutes[0].url.params.para[0].paraName != SIP_API_PNAME_LR)//if (sipUaDlgPtr->routeSets.recRoutes[0].params.para[0].paraName != SIP_API_PNAME_LR)
            {
                memcpy(&sipMsg->sipReStruct.sipReHdr.sipReqHdr.sipHdrRoutes.routes[0].url, &sipMsg->sipStartLine.requestUri, sizeof(SIP_URI));

                memcpy(&sipMsg->sipStartLine.requestUri, &sipUaDlgPtr->routeSets.recRoutes[0].url, sizeof(SIP_URI));

                sipMsg->sipReStruct.sipReHdr.sipReqHdr.sipHdrRoutes.head = 1;
            }

            sdMsg->sipTransAddr.addr.ipV4 = inet_addr(sipUaDlgPtr->routeSets.recRoutes[0].url.host.addr.domain);
            if (sipUaDlgPtr->routeSets.recRoutes[0].url.port != 0)
                sdMsg->sipTransAddr.port = sipUaDlgPtr->routeSets.recRoutes[0].url.port;
            else
                sdMsg->sipTransAddr.port = 5060;
//need forward develop
            sipMsg->sipReStruct.sipReHdrFlag[0] |= SIP_HDR_ROUTE_MASK;
        }
    }

    return 0;
}

int sip_ua_send_invite(BYTE cgId, WORD dialogId, WORD usrPort, SIP_API_STRUCT *sdMsg)//BYTE sapIndex
{
    int         port;
    BYTE        client;
    BYTE        method;
    int         ret;

    if ((dialogId >= SIP_UA_MAX_NUM_OF_DIALOG) || (sdMsg == NULL))
    {
        return -1;
    }

    if ((port = sip_ua_get_port()) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_invite:allocate port failed\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }
   
    client = SIP_TRANS_CLIENT;
    method = SIP_TRANS_INVITE;

    sdMsg->sipApiType = SIP_API_REQ_MSG;
    sdMsg->sipApiMsg.sipMsg.sipStartLine.sipMethod = SIP_METHOD_INVITE;
    sdMsg->sipApiMsg.sipMsg.sipStartLine.sipVersion = SIP_VERSION_2_0;
    sdMsg->sipApiMsg.sipMsg.sipHdrCseq.method = SIP_METHOD_INVITE;
    
    sdMsg->sipApiMsg.sipMsg.sipReStruct.sipReHdrFlag[0] |= SIP_HDR_MAX_FORWARDS_MASK;
    sdMsg->sipApiMsg.sipMsg.sipReStruct.sipReHdr.sipReqHdr.sipHdrMaxForwards.value = 70;

    if (sip_ua_fill_msg_with_dialog(dialogId, sdMsg) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_invite:fill msg with dialog failed\r\n");
        sip_log_err(sipAsciTempBuf);
        sip_ua_init_port(port);
        return -1;
    }

    if ((ret = sip_create_transaction(client, method, sipUaSipIndex, port, sdMsg)) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_invite:fill create transaction in sip failed\r\n");
        sip_log_err(sipAsciTempBuf);
        sip_ua_init_port(port);
        return -1;
    }

    strcpy(sipUaDialog[dialogId].invBranch, sdMsg->sipApiMsg.sipMsg.sipHdrVias.vias[0].params.para[0].para.paraStr);

    sipUaPort[port].sipuafState = SIP_UA_FSM_STATE_REQUEST;
    sipUaPort[port].dialogId = dialogId;
    sipUaPort[port].usrPort = usrPort;
    sipUaPort[port].cgId = cgId;//sipUaPort[port].sapIndex = sapIndex;
    sipUaPort[port].llPort = ret;
    sipUaPort[port].mainState = SIP_UA_MAIN_STATE_INVITE_REQ;
    sipUaPort[port].state = SIP_UA_SEND_REQUEST;

    memcpy(&sipUaPort[port].sdSipMsg, sdMsg, sizeof(SIP_API_STRUCT));

    sip_ua_set_send_cmd(&sipUaPort[port], sdMsg);

    sipUaDialog[dialogId].sipUaPort = port;
    sipUaDialog[dialogId].invUaPort.sdInvUaPort = port;
    
    sip_ua_fsm(port);

    return 0;
}

int sip_ua_send_re_invite(BYTE cgId, WORD dialogId, WORD usrPort, SIP_API_STRUCT *sdMsg)//BYTE sapIndex
{
    int         port;
    BYTE        client;
    BYTE        method;
    int         ret;

    if ((dialogId >= SIP_UA_MAX_NUM_OF_DIALOG) || (sdMsg == NULL))
    {
        return -1;
    }

    if ((port = sip_ua_get_port()) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_re_invite:allocate port failed\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }
   
    client = SIP_TRANS_CLIENT;
    method = SIP_TRANS_INVITE;

    sdMsg->sipApiType = SIP_API_REQ_MSG;
    sdMsg->sipApiMsg.sipMsg.sipStartLine.sipMethod = SIP_METHOD_RE_INVITE;
    sdMsg->sipApiMsg.sipMsg.sipStartLine.sipVersion = SIP_VERSION_2_0;
    sdMsg->sipApiMsg.sipMsg.sipHdrCseq.method = SIP_METHOD_RE_INVITE;
    
    sdMsg->sipApiMsg.sipMsg.sipReStruct.sipReHdrFlag[0] |= SIP_HDR_MAX_FORWARDS_MASK;
    sdMsg->sipApiMsg.sipMsg.sipReStruct.sipReHdr.sipReqHdr.sipHdrMaxForwards.value = 70;

    if (sip_ua_fill_msg_with_dialog(dialogId, sdMsg) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_re_invite:fill msg with dialog failed\r\n");
        sip_log_err(sipAsciTempBuf);
        sip_ua_init_port(port);
        return -1;
    }

    if ((ret = sip_create_transaction(client, method, sipUaSipIndex, port, sdMsg)) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_re_invite:fill create transaction in sip failed\r\n");
        sip_log_err(sipAsciTempBuf);
        sip_ua_init_port(port);
        return -1;
    }

    sipUaPort[port].sipuafState = SIP_UA_FSM_STATE_REQUEST;
    sipUaPort[port].dialogId = dialogId;
    sipUaPort[port].usrPort = usrPort;
    sipUaPort[port].cgId = cgId;//sipUaPort[port].sapIndex = sapIndex;
    sipUaPort[port].llPort = ret;
    sipUaPort[port].mainState = SIP_UA_MAIN_STATE_INVITE_REQ;
    sipUaPort[port].state = SIP_UA_SEND_REQUEST;

    memcpy(&sipUaPort[port].sdSipMsg, sdMsg, sizeof(SIP_API_STRUCT));

    sip_ua_set_send_cmd(&sipUaPort[port], sdMsg);

    sipUaDialog[dialogId].sipUaPort = port;
    
    sip_ua_fsm(port);

    return 0;
}

int sip_ua_send_non_inv(BYTE cgId, WORD dialogId, WORD usrPort, BYTE method, SIP_API_STRUCT *sdMsg)//BYTE sapIndex
{
    int         port;
    BYTE        client;
    BYTE        sipMethod;
    int         ret;

    if ((dialogId >= SIP_UA_MAX_NUM_OF_DIALOG) || (sdMsg == NULL))
    {
        return -1;
    }

    if ((port = sip_ua_get_port()) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_non_inv:allocate port failed, method = %d\r\n", method);
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    client = SIP_TRANS_CLIENT;
    sipMethod = SIP_TRANS_NON_INVITE;

    sdMsg->sipApiType = SIP_API_REQ_MSG;
    sdMsg->sipApiMsg.sipMsg.sipStartLine.sipMethod = method;
    sdMsg->sipApiMsg.sipMsg.sipStartLine.sipVersion = SIP_VERSION_2_0;
    sdMsg->sipApiMsg.sipMsg.sipHdrCseq.method = method;

    sdMsg->sipApiMsg.sipMsg.sipReStruct.sipReHdrFlag[0] |= SIP_HDR_MAX_FORWARDS_MASK;
    sdMsg->sipApiMsg.sipMsg.sipReStruct.sipReHdr.sipReqHdr.sipHdrMaxForwards.value = 70;

    if (sip_ua_fill_msg_with_dialog(dialogId, sdMsg) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_non_inv:fill msg with dialog failed, method = %d\r\n", method);
        sip_log_err(sipAsciTempBuf);
        sip_ua_init_port(port);
        return -1;
    }

    if (method == SIP_METHOD_CANCEL)
    {
        sdMsg->sipApiMsg.sipMsg.sipHdrVias.vias[sdMsg->sipApiMsg.sipMsg.sipHdrVias.head].params.para[0].paraName = SIP_API_PNAME_BRANCH;
        sdMsg->sipApiMsg.sipMsg.sipHdrVias.vias[sdMsg->sipApiMsg.sipMsg.sipHdrVias.head].params.para[0].paraType = SIP_API_PTYPE_STRING;
        strcpy(sdMsg->sipApiMsg.sipMsg.sipHdrVias.vias[sdMsg->sipApiMsg.sipMsg.sipHdrVias.head].params.para[0].para.paraStr,  sipUaDialog[dialogId].invBranch);
        sdMsg->sipApiMsg.sipMsg.sipHdrVias.vias[sdMsg->sipApiMsg.sipMsg.sipHdrVias.head].params.paraNum++;
    }

    if ((ret = sip_create_transaction(client, sipMethod, sipUaSipIndex, port, sdMsg)) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_non_inv:create transaction is sip failed, method = %d\r\n", method);
        sip_log_err(sipAsciTempBuf);
        sip_ua_init_port(port);
        return -1;
    }

    sipUaPort[port].sipuafState = SIP_UA_FSM_STATE_REQUEST;
    sipUaPort[port].dialogId = dialogId;
    sipUaPort[port].usrPort = usrPort;
    sipUaPort[port].cgId = cgId;//sipUaPort[port].sapIndex = sapIndex;
    sipUaPort[port].llPort = ret;
    sipUaPort[port].mainState = SIP_UA_MAIN_STATE_NON_INVITE_REQ;
    sipUaPort[port].state = SIP_UA_SEND_REQUEST;

    if (SIP_METHOD_ACK == method)
    {
        sipUaDialog[dialogId].uaAckPort = port;
    }

    memcpy(&sipUaPort[port].sdSipMsg, sdMsg, sizeof(SIP_API_STRUCT));

    sip_ua_set_send_cmd(&sipUaPort[port], sdMsg);

    sipUaDialog[dialogId].sipUaPort = port;

    sip_ua_fsm(port);

    return 0;
}

int sip_ua_send_options(BYTE cgId,WORD dialogId, WORD usrPort, SIP_API_STRUCT *sdMsg)//BYTE sapIndex
{
    int         port;
    BYTE        client;
    BYTE        method;
    int         ret;

    if (sdMsg == NULL)
        return -1;

    if (dialogId < SIP_UA_MAX_NUM_OF_DIALOG)
    {
        if (cgId != sipUaDialog[dialogId].cgId)
        {
            sprintf((char *)sipAsciTempBuf, "sip_ua_send_options:userIndex is wrong\r\n");
            sip_log_err(sipAsciTempBuf);
            return -1;
        }
    }

    if ((port = sip_ua_get_port()) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_options:allocate port failed\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    client = SIP_TRANS_CLIENT;
    method = SIP_TRANS_NON_INVITE;

    sdMsg->sipApiType = SIP_API_REQ_MSG;
    sdMsg->sipApiMsg.sipMsg.sipStartLine.sipMethod = SIP_METHOD_OPTIONS;
    sdMsg->sipApiMsg.sipMsg.sipStartLine.sipVersion = SIP_VERSION_2_0;
    sdMsg->sipApiMsg.sipMsg.sipHdrCseq.method = SIP_METHOD_OPTIONS;

    sdMsg->sipApiMsg.sipMsg.sipReStruct.sipReHdrFlag[0] |= SIP_HDR_MAX_FORWARDS_MASK;
    sdMsg->sipApiMsg.sipMsg.sipReStruct.sipReHdr.sipReqHdr.sipHdrMaxForwards.value = 70;

    if (dialogId < SIP_UA_MAX_NUM_OF_DIALOG)
    {
        if (sip_ua_fill_msg_with_dialog(dialogId, sdMsg) < 0)
        {
            sprintf((char *)sipAsciTempBuf, "sip_ua_send_options:fille msg with dialog failed\r\n");
            sip_log_err(sipAsciTempBuf);
            sip_ua_init_port(port);
            return -1;
        }

        sipUaDialog[dialogId].sipUaPort = port;
    }

    if ((ret = sip_create_transaction(client, method, sipUaSipIndex, port, sdMsg)) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_options:create transaction in sip failed\r\n");
        sip_log_err(sipAsciTempBuf);
        sip_ua_init_port(port);
        return -1;
    }

    sipUaPort[port].sipuafState = SIP_UA_FSM_STATE_REQUEST;
    sipUaPort[port].dialogId = dialogId;
    sipUaPort[port].usrPort = usrPort;
    sipUaPort[port].cgId = cgId;//sipUaPort[port].sapIndex = sapIndex;
    sipUaPort[port].llPort = ret;
    sipUaPort[port].mainState = SIP_UA_MAIN_STATE_NON_INVITE_REQ;
    sipUaPort[port].state = SIP_UA_SEND_REQUEST;

    memcpy(&sipUaPort[port].sdSipMsg, sdMsg, sizeof(SIP_API_STRUCT));

    sip_ua_set_send_cmd(&sipUaPort[port], sdMsg);

    sip_ua_fsm(port);

    return 0;
}

int sip_ua_send_register(BYTE cgId, WORD usrPort, SIP_API_STRUCT *sdMsg)//BYTE sapIndex
{
    int         port;
    BYTE     client;
    BYTE     method;
    int         ret;

    if (sdMsg == NULL)
        return -1;

    if ((port = sip_ua_get_port()) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_options:allocate port failed\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    client = SIP_TRANS_CLIENT;
    method = SIP_TRANS_NON_INVITE;

    sdMsg->sipApiType = SIP_API_REQ_MSG;
    sdMsg->sipApiMsg.sipMsg.sipStartLine.sipMethod = SIP_METHOD_REGISTER;
    sdMsg->sipApiMsg.sipMsg.sipStartLine.sipVersion = SIP_VERSION_2_0;

    sdMsg->sipApiMsg.sipMsg.sipHdrCseq.method = SIP_METHOD_REGISTER;
    sdMsg->sipApiMsg.sipMsg.sipHdrCseq.value = time(NULL);
    sdMsg->sipApiMsg.sipMsg.sipReStruct.sipReHdrFlag[0] |= SIP_HDR_CSEQ_MASK;

    sdMsg->sipApiMsg.sipMsg.sipReStruct.sipReHdr.sipReqHdr.sipHdrMaxForwards.value = 70;
    sdMsg->sipApiMsg.sipMsg.sipReStruct.sipReHdrFlag[0] |= SIP_HDR_MAX_FORWARDS_MASK;

    if (sip_ua_create_register_tag(port, &sdMsg->sipApiMsg.sipMsg.sipHdrFrom.params.para[0]) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_create_register_tag:create tag failed\r\n");
        sip_log_err(sipAsciTempBuf);
        sip_ua_init_port(port);
        return -1;
    }

    sdMsg->sipApiMsg.sipMsg.sipHdrFrom.params.paraNum++;
    sdMsg->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_FROM_MASK;

    if (sip_ua_create_register_call_id(usrPort, &sdMsg->sipApiMsg.sipMsg.sipHdrCallId) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_create_register_tag:create call id failed\r\n");
        sip_log_err(sipAsciTempBuf);
        sip_ua_init_port(port);
        return -1;
    }

    sdMsg->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_CALL_ID_MASK;

/*    if (dialogId < SIP_UA_MAX_NUM_OF_DIALOG)
    {
        if (sip_ua_fill_msg_with_dialog(dialogId, sdMsg) < 0)
        {
            sprintf(sipAsciTempBuf, "sip_ua_send_options:fille msg with dialog failed\r\n");
            sip_log_err(sipAsciTempBuf);
            sip_ua_init_port(port);
            return -1;
        }

        sipUaDialog[dialogId].sipUaPort = port;
    }*/

    if ((ret = sip_create_transaction(client, method, sipUaSipIndex, port, sdMsg)) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_options:create transaction in sip failed\r\n");
        sip_log_err(sipAsciTempBuf);
        sip_ua_init_port(port);
        return -1;
    }

    sipUaPort[port].sipuafState = SIP_UA_FSM_STATE_REQUEST;
    sipUaPort[port].dialogId = SIP_UA_NULL_DIALOG;//dialogId
    sipUaPort[port].usrPort = usrPort;
    sipUaPort[port].cgId = cgId;//sipUaPort[port].sapIndex = sapIndex;
    sipUaPort[port].llPort = ret;
    sipUaPort[port].mainState = SIP_UA_MAIN_STATE_NON_INVITE_REQ;
    sipUaPort[port].state = SIP_UA_SEND_REQUEST;

    memcpy(&sipUaPort[port].sdSipMsg, sdMsg, sizeof(SIP_API_STRUCT));

    sip_ua_set_send_cmd(&sipUaPort[port], sdMsg);

    sip_ua_fsm(port);

    return 0;
}


int sip_ua_set_inv_temp_rsp(WORD uaPort,SIP_API_STRUCT *sdMsg)
{
    BYTE        client;
    BYTE        method;
    int         ret;

    if (sdMsg == NULL)
        return -1;

    if ((uaPort >= SIP_UA_MAX_NUM_OF_PORT) || (sipUaPort[uaPort].flag != 1))
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_inv_temp_rsp:ua port wrong\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    client = SIP_TRANS_SERVER;
    method = SIP_TRANS_INVITE;

    sdMsg->sipApiType = SIP_API_RES_MSG;
    sdMsg->sipApiMsg.sipMsg.sipStartLine.sipMethod = SIP_METHOD_INVITE;
    sdMsg->sipApiMsg.sipMsg.sipStartLine.sipVersion = SIP_VERSION_2_0;
    sdMsg->sipApiMsg.sipMsg.sipHdrCseq.method = SIP_METHOD_INVITE;

    if ((ret = sip_create_transaction(client, method, sipUaSipIndex, uaPort, sdMsg)) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_inv_rsp:create transaction in sip failed no proc port\r\n");
        sip_log_err(sipAsciTempBuf);
        sip_ua_init_port(uaPort);
        return -1;
    }

    sipUaPort[uaPort].llPort = ret;

    return 0;
}

int sip_ua_send_inv_rsp(BYTE cgId,WORD dialogId, WORD usrPort, SIP_API_STRUCT *sdMsg)//BYTE cgId
{
    BYTE        client;
    BYTE        method;
    int            ret;
    WORD      uaPort;

    if (sdMsg == NULL)
        return -1;

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

    if (cgId != sipUaDialog[dialogId].cgId)//if (sapIndex != sipUaDialog[dialogId].userIndex)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_inv_rsp:cgId wrong\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    uaPort = sipUaDialog[dialogId].sipUaPort;

    if ((uaPort >= SIP_UA_MAX_NUM_OF_PORT) || (sipUaPort[uaPort].flag != 1))
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_inv_rsp:ua port wrong\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    if (!((sipUaDialog[dialogId].uaPort == 0xFFFF) || (sipUaDialog[dialogId].uaPort == uaPort)))
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_inv_rsp:dialog ua port not match\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    client = SIP_TRANS_SERVER;
    method = SIP_TRANS_INVITE;

    sdMsg->sipApiType = SIP_API_RES_MSG;
    sdMsg->sipApiMsg.sipMsg.sipStartLine.sipMethod = SIP_METHOD_INVITE;
    sdMsg->sipApiMsg.sipMsg.sipStartLine.sipVersion = SIP_VERSION_2_0;
    sdMsg->sipApiMsg.sipMsg.sipHdrCseq.method = SIP_METHOD_INVITE;

    if (sip_ua_fill_msg_with_dialog(dialogId, sdMsg) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_inv_rsp:fill msg with dialog failed no proc port\r\n");
        sip_log_err(sipAsciTempBuf);
        sip_ua_init_port(uaPort);
        return -1;
    }

    if (sipUaPort[uaPort].llPort == 0xFFFF)
    {
        if ((ret = sip_create_transaction(client, method, sipUaSipIndex, uaPort, sdMsg)) < 0)
        {
            sprintf((char *)sipAsciTempBuf, "sip_ua_send_inv_rsp:create transaction in sip failed no proc port\r\n");
            sip_log_err(sipAsciTempBuf);
            sip_ua_init_port(uaPort);
            return -1;
        }

        sipUaPort[uaPort].dialogId = dialogId;
        sipUaPort[uaPort].usrPort = usrPort;
        sipUaPort[uaPort].cgId = cgId;//sipUaPort[uaPort].sapIndex = sapIndex;
        sipUaPort[uaPort].llPort = ret;
    }

    if (sipUaPort[uaPort].usrPort == 0xFFFF)//if (sipUaDialog[dialogId].uaPort == 0xFFFF)
    {
        sipUaPort[uaPort].dialogId = dialogId;
        sipUaPort[uaPort].usrPort = usrPort;
        sipUaPort[uaPort].cgId = cgId;//sipUaPort[uaPort].sapIndex = sapIndex;
        sipUaPort[uaPort].state = SIP_UA_SEND_RESPONSE;
        sipUaPort[uaPort].timer = SIP_UA_TIMER_TIME_OUT;
    }

    memcpy(&sipUaPort[uaPort].sdSipMsg, sdMsg, sizeof(SIP_API_STRUCT));

    sip_ua_set_send_cmd(&sipUaPort[uaPort], sdMsg);

    sipUaDialog[dialogId].uaPort = uaPort;

    sip_ua_fsm(uaPort);

    return 0;
}

int sip_ua_send_cancel_inv_rsp(BYTE cgId,WORD dialogId, WORD usrPort, SIP_API_STRUCT *sdMsg)//BYTE sapIndex
{
    BYTE        client;
    BYTE        method;
    int            ret;
    WORD      uaPort;

    if (sdMsg == NULL)
        return -1;

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

    if (cgId != sipUaDialog[dialogId].cgId)//if (sapIndex != sipUaDialog[dialogId].userIndex)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_cancel_inv_rsp:userIndex wrong\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    uaPort = sipUaDialog[dialogId].invUaPort.rvInvUaPort;

    if ((uaPort >= SIP_UA_MAX_NUM_OF_PORT) || (sipUaPort[uaPort].flag != 1))
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_cancel_inv_rsp:ua port wrong\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    if (!((sipUaDialog[dialogId].uaPort == 0xFFFF) || (sipUaDialog[dialogId].uaPort == uaPort)))
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_cancel_inv_rsp:dialog ua port not match\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    client = SIP_TRANS_SERVER;
    method = SIP_TRANS_INVITE;

    sdMsg->sipApiType = SIP_API_RES_MSG;
    sdMsg->sipApiMsg.sipMsg.sipStartLine.sipMethod = SIP_METHOD_INVITE;
    sdMsg->sipApiMsg.sipMsg.sipStartLine.sipVersion = SIP_VERSION_2_0;
    sdMsg->sipApiMsg.sipMsg.sipHdrCseq.method = SIP_METHOD_INVITE;

    if (sip_ua_fill_msg_with_dialog(dialogId, sdMsg) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_cancel_inv_rsp:fill msg with dialog failed no proc port\r\n");
        sip_log_err(sipAsciTempBuf);
        sip_ua_init_port(uaPort);
        return -1;
    }

    if (sipUaPort[uaPort].llPort == 0xFFFF)
    {
        if ((ret = sip_create_transaction(client, method, sipUaSipIndex, uaPort, sdMsg)) < 0)
        {
            sprintf((char *)sipAsciTempBuf, "sip_ua_send_inv_rsp:create transaction in sip failed no proc port\r\n");
            sip_log_err(sipAsciTempBuf);
            sip_ua_init_port(uaPort);
            return -1;
        }

        sipUaPort[uaPort].dialogId = dialogId;
        sipUaPort[uaPort].usrPort = usrPort;
        sipUaPort[uaPort].cgId = cgId;//sipUaPort[uaPort].sapIndex = sapIndex;
        sipUaPort[uaPort].llPort = ret;
    }

    if (sipUaPort[uaPort].usrPort == 0xFFFF)//if (sipUaDialog[dialogId].uaPort == 0xFFFF)
    {
        sipUaPort[uaPort].dialogId = dialogId;
        sipUaPort[uaPort].usrPort = usrPort;
        sipUaPort[uaPort].cgId = cgId;//sipUaPort[uaPort].sapIndex = sapIndex;
        sipUaPort[uaPort].state = SIP_UA_SEND_RESPONSE;
        sipUaPort[uaPort].timer = SIP_UA_TIMER_TIME_OUT;
    }

    memcpy(&sipUaPort[uaPort].sdSipMsg, sdMsg, sizeof(SIP_API_STRUCT));

    sip_ua_set_send_cmd(&sipUaPort[uaPort], sdMsg);

    sipUaDialog[dialogId].uaPort = uaPort;

    sip_ua_fsm(uaPort);

    return 0;
}

int sip_ua_send_re_inv_rsp(BYTE cgId,WORD dialogId, WORD usrPort, SIP_API_STRUCT *sdMsg)//BYTE sapIndex
{
    BYTE        client;
    BYTE        method;
    int            ret;
    WORD      uaPort;

    if (sdMsg == NULL)
        return -1;

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

    if (cgId != sipUaDialog[dialogId].cgId)//if (sapIndex != sipUaDialog[dialogId].userIndex)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_re_inv_rsp:userIndex wrong\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    uaPort = sipUaDialog[dialogId].sipUaPort;

    if ((uaPort >= SIP_UA_MAX_NUM_OF_PORT) || (sipUaPort[uaPort].flag != 1))
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_re_inv_rsp:ua port wrong\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    client = SIP_TRANS_SERVER;
    method = SIP_TRANS_INVITE;

    sdMsg->sipApiType = SIP_API_RES_MSG;
    sdMsg->sipApiMsg.sipMsg.sipStartLine.sipMethod = SIP_METHOD_RE_INVITE;
    sdMsg->sipApiMsg.sipMsg.sipStartLine.sipVersion = SIP_VERSION_2_0;
    sdMsg->sipApiMsg.sipMsg.sipHdrCseq.method = SIP_METHOD_RE_INVITE;

    if (sip_ua_fill_msg_with_dialog(dialogId, sdMsg) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_re_inv_rsp:fill msg with dialog failed no proc port\r\n");
        sip_log_err(sipAsciTempBuf);
        sip_ua_init_port(uaPort);
        return -1;
    }

    if ((ret = sip_create_transaction(client, method, sipUaSipIndex, uaPort, sdMsg)) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_re_inv_rsp:create transaction in sip failed no proc port\r\n");
        sip_log_err(sipAsciTempBuf);
        sip_ua_init_port(uaPort);
        return -1;
    }

    sipUaPort[uaPort].dialogId = dialogId;
    sipUaPort[uaPort].usrPort = usrPort;
    sipUaPort[uaPort].cgId = cgId;//sipUaPort[uaPort].sapIndex = sapIndex;
    sipUaPort[uaPort].llPort = ret;
    sipUaPort[uaPort].state = SIP_UA_SEND_RESPONSE;
    sipUaPort[uaPort].timer = SIP_UA_TIMER_TIME_OUT;

    memcpy(&sipUaPort[uaPort].sdSipMsg, sdMsg, sizeof(SIP_API_STRUCT));

    sip_ua_set_send_cmd(&sipUaPort[uaPort], sdMsg);

    sipUaDialog[dialogId].uaPort = uaPort;

    sip_ua_fsm(uaPort);

    return 0;
}

int sip_ua_send_non_inv_rsp(BYTE cgId, WORD dialogId, WORD usrPort, BYTE method, SIP_API_STRUCT *sdMsg)//BYTE sapIndex
{
    BYTE        client;
    BYTE        sipMethod;
    int            ret;
    WORD      uaPort=0xFFFF;

    if (sdMsg == NULL)
        return -1;

    if ((method != SIP_METHOD_OPTIONS) && (dialogId >= SIP_UA_MAX_NUM_OF_DIALOG))
    {
        return -1;
    }

    if (dialogId < SIP_UA_MAX_NUM_OF_DIALOG)
    {
        if (cgId != sipUaDialog[dialogId].cgId)
            return -1;
    }
        
    client = SIP_TRANS_SERVER;
    sipMethod = SIP_TRANS_NON_INVITE;

    sdMsg->sipApiType = SIP_API_RES_MSG;
    sdMsg->sipApiMsg.sipMsg.sipStartLine.sipMethod = method;
    sdMsg->sipApiMsg.sipMsg.sipStartLine.sipVersion = SIP_VERSION_2_0;
    sdMsg->sipApiMsg.sipMsg.sipHdrCseq.method = method;

    if (dialogId < SIP_UA_MAX_NUM_OF_DIALOG)
    {
        if (sip_ua_fill_msg_with_dialog(dialogId, sdMsg) < 0)
        {
            sprintf((char *)sipAsciTempBuf, "sip_ua_send_non_inv_rsp:fill msg with dialog failed\r\n");
            sip_log_err(sipAsciTempBuf);
            sip_ua_init_port(uaPort);
            return -1;
        }

        uaPort = sipUaDialog[dialogId].sipUaPort;
    }

    if (uaPort >= SIP_UA_MAX_NUM_OF_PORT)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_non_inv_rsp:uaPort wrong\r\n");
        sip_log_err(sipAsciTempBuf);
        sip_ua_init_port(uaPort);
        return -1;
    }

    if ((ret = sip_create_transaction(client, sipMethod, sipUaSipIndex, uaPort, sdMsg)) < 0)
    {
        sprintf((char *)sipAsciTempBuf, "sip_ua_send_non_inv_rsp:create transaction in sip failed\r\n");
        sip_log_err(sipAsciTempBuf);
        sip_ua_init_port(uaPort);
        return -1;
    }

    sipUaPort[uaPort].dialogId = dialogId;
    sipUaPort[uaPort].usrPort = usrPort;
    sipUaPort[uaPort].cgId = cgId;//sipUaPort[uaPort].sapIndex = sapIndex;
    sipUaPort[uaPort].llPort = ret;
    sipUaPort[uaPort].state = SIP_UA_SEND_RESPONSE;

    memcpy(&sipUaPort[uaPort].sdSipMsg, sdMsg, sizeof(SIP_API_STRUCT));

    sip_ua_set_send_cmd(&sipUaPort[uaPort], sdMsg);

    sip_ua_fsm(uaPort);

    return 0;
}
