#include "./include/sip_pub.h"
#include "./include/sip.h"
#include "./include/sip_const.h"
#include "./include/sip_struct.h"
#include "./include/sip_ext.h"
#include "./include/sip_transport.h"
#include "./include/sip_msg.h"

int sip_create_trans_branch(WORD transId, SIP_GEN_PARA *branch)
{
    branch->paraName = SIP_API_PNAME_BRANCH;
    branch->paraType = SIP_API_PTYPE_STRING;
    sprintf(branch->para.paraStr, "z9hG4bk-%d-%ld", SIP_BRANCH_BASE_TRANS_ID + transId, time(NULL));
    
    return 0;
}

DWORD sip_min(DWORD A, DWORD B)
{
    if (A <= B)
        return A;
        
    return B;
}

void sip_trans_init(WORD trans_id)
{
    memset((BYTE *)&sipTrans[trans_id], 0, sizeof(SIP_TRANSACTION));
}

int sip_request_uri_match(SIP_URI *uriFirst, SIP_URI *uriSecond)
{
    if (strcmp(uriFirst->userName, uriSecond->userName) != 0)
        return -1;
    
    if (strcmp(uriFirst->host.addr.domain, uriSecond->host.addr.domain) != 0)
        return -1;
    
    return 0;
}

int sip_call_id_match(SIP_HDR_CALL_ID *callIdFirst, SIP_HDR_CALL_ID *callIdSecond)
{
    if (strcmp(callIdFirst->value, callIdSecond->value) !=0)
        return -1;
    
    if (strcmp(callIdFirst->host, callIdSecond->host) != 0)
        return -1;
    
    return 0;
}

int sip_top_via_match(SIP_HDR_VIA *viaFirst, SIP_HDR_VIA *viaSecond)
{
    if (strcmp(viaFirst->url.domain, viaSecond->url.domain) != 0)
        return -1;
    
    return 0;
}

WORD sip_request_match_server_trans(SIP_API_STRUCT *recvMsg)
{
    WORD            transId;
    char            *branchRecvd, *branchCreated;
    char            *sentByRecvd, *sentByCreated;
    char            methodRecvd, methodCreated;
    SIP_MSG         *sipMsgRecvd;
	SIP_CR_MSG      *sipMsgCreated;
    SIP_URI         *requestUriRecvd, *requestUriCreated;
    char            *toTagRecvd, *toTagCreated;//, *toTagResponse;//improve
    char            *fromTagRecvd, *fromTagCreated;
    SIP_HDR_CALL_ID *callIdRecvd, *callIdCreated;
    SIP_HDR_CSEQ    *cseqRecvd, *cseqCreated;
    SIP_HDR_VIA     *viaRecvd, *viaCreated;
    
    sipMsgRecvd = &recvMsg->sipApiMsg.sipMsg;
    methodRecvd = sipMsgRecvd->sipStartLine.sipMethod;
    viaRecvd    = &sipMsgRecvd->sipHdrVias.vias[1];
    branchRecvd = viaRecvd->params.para[0].para.paraStr;
    
    if (strncmp(branchRecvd, "z9hG4bK", 7) == 0)
    {   // RFC 3261
        sentByRecvd = sipMsgRecvd->sipHdrVias.vias[1].url.domain;
        
        for (transId = 0; transId < SIP_MAX_NUM_OF_TRANS; transId++)
        {
            if ((sipTrans[transId].flag != 1) ||
                (sipTrans[transId].client != SIP_TRANS_SERVER))
                continue;

            sipMsgCreated   = &sipTrans[transId].crMsg;
            branchCreated = sipMsgCreated->sipCrHdrVia.params.para[0].para.paraStr;
            sentByCreated = sipMsgCreated->sipCrHdrVia.url.domain;
            methodCreated = sipMsgCreated->sipCrStartLine.sipMethod;
            
            if ((strcmp(branchRecvd, branchCreated) == 0) &&
                (strcmp(sentByRecvd, sentByCreated) == 0))//
            {
                if (methodRecvd == SIP_METHOD_ACK)
                    return transId;
                else if (methodRecvd == methodCreated)
                    return transId;
            }
        }
    }
    
    // RFC 2543
    
    requestUriRecvd = &sipMsgRecvd->sipStartLine.requestUri;
    toTagRecvd      = sipMsgRecvd->sipHdrTo.params.para[0].para.paraStr;
    fromTagRecvd    = sipMsgRecvd->sipHdrFrom.params.para[0].para.paraStr;
    callIdRecvd     = &sipMsgRecvd->sipHdrCallId;
    cseqRecvd       = &sipMsgRecvd->sipHdrCseq;
    
    for (transId = 0; transId < SIP_MAX_NUM_OF_TRANS; transId++)
    {
        if ((sipTrans[transId].flag != 1) ||
            (sipTrans[transId].client != SIP_TRANS_SERVER))
            continue;

        sipMsgCreated       = &sipTrans[transId].crMsg;
        requestUriCreated   = &sipMsgCreated->sipCrStartLine.requestUri;
        toTagCreated        = sipMsgCreated->sipCrHdrTo.params.para[0].para.paraStr;
//        toTagResponse       = sipTrans[transId].sdMsg.sipApiMsg.sipMsg.sipHdrTo.params.para[0].para.paraStr;//improve
        fromTagCreated      = sipMsgCreated->sipCrHdrFrom.params.para[0].para.paraStr;
        callIdCreated       = &sipMsgCreated->sipCrHdrCallId;
        cseqCreated         = &sipMsgCreated->sipCrHdrCseq;
        viaCreated          = &sipMsgCreated->sipCrHdrVia;
        
        if ((sip_request_uri_match(requestUriRecvd, requestUriCreated) == 0) &&
            (strcmp(fromTagRecvd, fromTagCreated) == 0) &&
            (sip_call_id_match(callIdRecvd, callIdCreated) == 0) &&
            (cseqRecvd->value == cseqCreated->value) &&
            (sip_top_via_match(viaRecvd, viaCreated) == 0))
        {
            if (methodRecvd == SIP_METHOD_ACK)
            {
                if (strcmp(toTagRecvd, toTagCreated) == 0)//if (strcmp(toTagRecvd, toTagResponse) == 0)//improve
                    return transId;
            }
            else
            {
                if ((strcmp(toTagRecvd, toTagCreated) == 0) &&
                    (cseqRecvd->method == cseqCreated->method))
                    return transId;
            }
        }
    }
    
    return SIP_MAX_NUM_OF_TRANS;
}

WORD sip_response_match_client_trans(SIP_API_STRUCT *recvMsg)
{
    char            *first;
    char            *second;
    char            tmp[8] = "";
    char            *branchRecvd, *branchCreated;
    BYTE            methodRecvd, methodCreated;
    WORD            transId;
    
    branchRecvd = recvMsg->sipApiMsg.sipMsg.sipHdrVias.vias[1].params.para[0].para.paraStr;
    
    first = strchr(branchRecvd, '-');
    if (first == NULL)
        return SIP_MAX_NUM_OF_TRANS;
    
    second = strchr(first + 1, '-');
    if (second == NULL)
        return SIP_MAX_NUM_OF_TRANS;
    
    if ((second - first - 1) != SIP_BRANCH_BASE_TRANS_ID_LEN)
        return SIP_MAX_NUM_OF_TRANS;
    strncpy(tmp, first + 1, SIP_BRANCH_BASE_TRANS_ID_LEN);
    
    transId = atol(tmp);
    transId = transId - SIP_BRANCH_BASE_TRANS_ID;
    if (transId >= SIP_MAX_NUM_OF_TRANS)
        return SIP_MAX_NUM_OF_TRANS;
    
    methodRecvd     = recvMsg->sipApiMsg.sipMsg.sipHdrCseq.method;

    methodCreated   = sipTrans[transId].crMsg.sipCrHdrCseq.method;
    branchCreated   = sipTrans[transId].crMsg.sipCrHdrVia.params.para[0].para.paraStr;
    
    if ((strcmp(branchRecvd, branchCreated) == 0) &&
        (methodRecvd == methodCreated))
        return transId;
    else
    {   
        for (transId = 0; transId < SIP_MAX_NUM_OF_TRANS; transId++)
        {
            if ((sipTrans[transId].flag != 1) ||
                (sipTrans[transId].client != SIP_TRANS_CLIENT))
                continue;

            methodCreated   = sipTrans[transId].crMsg.sipCrHdrCseq.method;
            branchCreated   = sipTrans[transId].crMsg.sipCrHdrVia.params.para[0].para.paraStr;

            if ((strcmp(branchRecvd, branchCreated) == 0) &&
                (methodRecvd == methodCreated))
                return transId;
        }
    }
    
    return SIP_MAX_NUM_OF_TRANS;
}

int sip_trans_srv_non_inv_proc(WORD transId)
{
    SIP_TRANSACTION     *sipTransPtr;
    WORD                sdCmd;
    WORD                rvCmd;
    SIP_USER            *sipUser;
    
    sipTransPtr = &sipTrans[transId];
    sdCmd = sipTransPtr->sdCmd;
    rvCmd = sipTransPtr->rvCmd;
    sipUser = &sipUsers.sipUsers[sipTransPtr->userIndex].sipUser;
    
    switch (sipTransPtr->state)
    {
        case SIP_TRANS_STATE_IDLE:
            // Request received, pass to TU
            sipTransPtr->state = SIP_TRANS_STATE_TRYING;
            sipTransPtr->timer = (18 * SIP_TIMER_T4);
            return sip_trans_srv_non_inv_proc(transId);
        case SIP_TRANS_STATE_TRYING:
            if (sdCmd != SIP_COMMAND_IDLE)
            {
                sipTransPtr->sdCmd = SIP_COMMAND_IDLE;
                if ((sdCmd >= 100) && (sdCmd <= 199))
                {   // If 1XX from TU, send response
                    sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
//                    sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
                    sipTransPtr->state = SIP_TRANS_STATE_PROCEEDING;
                    sipTransPtr->timer = (18 * SIP_TIMER_T4);
                }
                else if ((sdCmd >= 200) && (sdCmd <= 699))
                {   // If 200-699 from TU, send response
                    sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
//                    sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
                    sipTransPtr->state = SIP_TRANS_STATE_COMPLETED;
                    sipTransPtr->timer = SIP_TIMER_J;
                }
            }

            if ((SIP_TRANS_STATE_TRYING == sipTransPtr->state) && (sipTransPtr->timer > 0))
            {
                if (--sipTransPtr->timer == 0)
                {
                    sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                    return 1;
                }
            }
            break;
        case SIP_TRANS_STATE_PROCEEDING:
            if (sdCmd != SIP_COMMAND_IDLE)
            {
                sipTransPtr->sdCmd = SIP_COMMAND_IDLE;
                if ((sdCmd >= 100) && (sdCmd <= 199))
                {   // If 1XX from TU, send response
                    sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
//                    sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
                }
                else if ((sdCmd >= 200) && (sdCmd <= 699))
                {   // If 200-699 from TU, send response
                    sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
//                    sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
                    sipTransPtr->state = SIP_TRANS_STATE_COMPLETED;
                    sipTransPtr->timer = SIP_TIMER_J;
                    return 0;
                }
            }
            
            if (rvCmd != SIP_COMMAND_IDLE)
            {
                sipTransPtr->rvCmd = SIP_COMMAND_IDLE;
                if (rvCmd == SIP_TRANSPORT_ERROR)
                {   // If transport error, inform TU
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
                    sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                    return 1;
                }
                else
                {   // If request, send response
                    sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
//                    sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
                }
            }

            if ((SIP_TRANS_STATE_PROCEEDING == sipTransPtr->state) && (sipTransPtr->timer > 0))
            {
                if (--sipTransPtr->timer == 0)
                {
                    sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                    return 1;
                }
            }
            
            break;
        case SIP_TRANS_STATE_COMPLETED:
            if (rvCmd != SIP_COMMAND_IDLE)
            {
                sipTransPtr->rvCmd = SIP_COMMAND_IDLE;
                // Request, send response
                if (rvCmd == SIP_TRANSPORT_ERROR)
                {   // If transport error, inform TU
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
                    sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                    return 1;
                }
                else
                {   // If request, send response
                    sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
//                    sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
                }
            }
            
            if (sipTransPtr->timer > 0)
                sipTransPtr->timer--;
                
            if (sipTransPtr->timer == 0)
            {   // if timer J fires
                sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                return 1;
            }
            break;
        default:
            sipTransPtr->state = SIP_TRANS_STATE_IDLE;
            break;
    }
    
    return 0;
}

int sip_trans_srv_inv_proc(WORD transId)
{
    SIP_TRANSACTION     *sipTransPtr;
    WORD                sdCmd;
    WORD                rvCmd;
    SIP_USER            *sipUser;
    
    sipTransPtr = &sipTrans[transId];
    sdCmd = sipTransPtr->sdCmd;
    rvCmd = sipTransPtr->rvCmd;
    sipUser = &sipUsers.sipUsers[sipTransPtr->userIndex].sipUser;
    
    switch (sipTransPtr->state)
    {
        case SIP_TRANS_STATE_IDLE:
            // INVITE received, pass to TU
            sipTransPtr->timer2= SIP_TIMER_200MS;
            sipTransPtr->timer = (18 * SIP_TIMER_T4);
            sipTransPtr->state = SIP_TRANS_STATE_PROCEEDING;
            return sip_trans_srv_inv_proc(transId);
            break;
        case SIP_TRANS_STATE_PROCEEDING:
            if (sdCmd != SIP_COMMAND_IDLE)
            {
                sipTransPtr->sdCmd = SIP_COMMAND_IDLE;
                if ((sdCmd >= 101) && (sdCmd <= 199))
                {   // if 101-199 from TU, send response
                    sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
//                    sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
                    sipTransPtr->timer2 = 0;
                }
                else if ((sdCmd >= 200) && (sdCmd <= 299))
                {   // if 2xx from TU, send response
                    sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
//                    sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
                    sipTransPtr->timer2 = 0;
                    sipTransPtr->timer = 0;
                    sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                    return 1;
                }
                else if ((sdCmd >= 300) && (sdCmd <= 699))
                {   // if 300-699 from TU, send response
                    sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
//                    sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
                    sipTransPtr->state = SIP_TRANS_STATE_COMPLETED;
                    sipTransPtr->timer2 = SIP_TIMER_G;
                    sipTransPtr->timer = SIP_TIMER_H;
                    return 0;
                }
            }
            
            if (rvCmd != SIP_COMMAND_IDLE)
            {
                sipTransPtr->rvCmd = SIP_COMMAND_IDLE;
                if (rvCmd == SIP_TRANSPORT_ERROR)
                {   // If transport error, inform TU
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
                    sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                    return 1;
                }
                else if (rvCmd == SIP_METHOD_INVITE)
                {   // If INVITE, send response
                    sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
//                        sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
                }
            }
            
            if ((SIP_TRANS_STATE_PROCEEDING == sipTransPtr->state) && (sipTransPtr->timer2 > 0))
            {
                if (--sipTransPtr->timer2== 0)
                    sip_send_100(&sipTransPtr->crMsg, sipTransPtr);
            }

            if ((SIP_TRANS_STATE_PROCEEDING == sipTransPtr->state) && (sipTransPtr->timer > 0))
            {
                if (--sipTransPtr->timer == 0)
                {
                    sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                    return 1;
                }
            }
            break;
        case SIP_TRANS_STATE_COMPLETED:
            if (rvCmd != SIP_COMMAND_IDLE)
            {
                sipTransPtr->rvCmd = SIP_COMMAND_IDLE;
                if (rvCmd == SIP_TRANSPORT_ERROR)
                {   // If transport error, inform TU
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
                    sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                    return 1;
                }
                else if (rvCmd == SIP_METHOD_ACK)
                {   // If ACK
                    sipTransPtr->state = SIP_TRANS_STATE_CONFIRMED;
                    sipTransPtr->timer = SIP_TIMER_I;
                    return 0;
                }
                else if (rvCmd == SIP_METHOD_INVITE)
                {   // If INVITE, send response
                    sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
//                    sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
                }
            }

            if ((SIP_TRANS_STATE_COMPLETED == sipTransPtr->state) && (sipTransPtr->timer2 > 0))
            {
                if (--sipTransPtr->timer2 == 0)
                {// If timer G fires, send response
                    sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
//                    sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
                    sipTransPtr->retransTimes++;
                    sipTransPtr->timer2 = sip_min((1 << sipTransPtr->retransTimes) * SIP_TIMER_E_INITIAL, SIP_TIMER_T2);
                }
            }
            
            if ((SIP_TRANS_STATE_COMPLETED == sipTransPtr->state) && (sipTransPtr->timer > 0))
            {
                if (--sipTransPtr->timer == 0)
                {   // If timer H fires
                    sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                    return 1;
                }
            }
            break;
        case SIP_TRANS_STATE_CONFIRMED:
            if (sipTransPtr->timer > 0)
                sipTransPtr->timer--;
            
            if (sipTransPtr->timer == 0)
            {   // If timer I fires
                sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                return 1;
            }
            break;
        default:
            sipTransPtr->state = SIP_TRANS_STATE_IDLE;
            break;
    }
    
    return 0;
}

int sip_trans_clt_non_inv_proc(WORD transId)
{
    SIP_TRANSACTION     *sipTransPtr;
    SIP_USER            *sipUser;
    WORD                sdCmd;
    WORD                rvCmd;
    
    sipTransPtr = &sipTrans[transId];
    sdCmd = sipTransPtr->sdCmd;
    rvCmd = sipTransPtr->rvCmd;
    sipUser = &sipUsers.sipUsers[sipTransPtr->userIndex].sipUser;
    
    switch (sipTransPtr->state)
    {
        case SIP_TRANS_STATE_IDLE:
            if (sdCmd != SIP_COMMAND_IDLE)
            {
                sipTransPtr->sdCmd = SIP_COMMAND_IDLE;
                if (sdCmd != SIP_METHOD_INVITE)
                {   // Request from TU, send request
//                    sip_fill_cr_msg(&sipTransPtr->crMsg, &sipTransPtr->sdMsg);//improve
                    sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
//                    sip_transport_send_msg(&sipTransPtr->sdMsg);//improve

                    if (sdCmd == SIP_METHOD_ACK)
                    {
                        sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                        return 1;
                    }
                    else
                    {
                        sipTransPtr->timer = SIP_TIMER_F;
                        sipTransPtr->timer2 = SIP_TIMER_E_INITIAL;
                        sipTransPtr->retransTimes = 0;
                        sipTransPtr->state = SIP_TRANS_STATE_TRYING;
                    }
                }
                else
                    return 1;
            }
            break;
        case SIP_TRANS_STATE_TRYING:
            if (rvCmd != SIP_COMMAND_IDLE)
            {
                sipTransPtr->rvCmd = SIP_COMMAND_IDLE;
                if ((rvCmd >= 200) & (rvCmd <= 699))
                {   // 200-699, resp. to TU
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
                    sipTransPtr->state = SIP_TRANS_STATE_COMPLETED;
                    sipTransPtr->timer = SIP_TIMER_K;
                    return 0;
                }
                else if (rvCmd == SIP_TRANSPORT_ERROR)
                {   // Transport error, inform TU
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
                    sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                    return 1;
                }
                else if ((rvCmd >= 100) & (rvCmd <= 199))
                {   // 1xx, 1xx to TU
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
                    sipTransPtr->state = SIP_TRANS_STATE_PROCEEDING;
                    sipTransPtr->timer = SIP_TIMER_F;
//                    sipTransPtr->timer2 = SIP_TIMER_T2;//??
                    return 0;
                }
            }
            
            if ((SIP_TRANS_STATE_TRYING == sipTransPtr->state) && (sipTransPtr->timer2 > 0))
            {
                if (--sipTransPtr->timer2 == 0)
                {// Timer E fires, send request
                    sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
//                    sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
                    sipTransPtr->retransTimes++;
                    sipTransPtr->timer2 = sip_min((1 << sipTransPtr->retransTimes) * SIP_TIMER_E_INITIAL, SIP_TIMER_T2);
                }
            }
            
            if ((SIP_TRANS_STATE_TRYING == sipTransPtr->state) && (sipTransPtr->timer > 0))
            {
                if (--sipTransPtr->timer == 0)
                {// If timer F fires, inform TU
/*                    memset(&sipToUpMsg, 0, sizeof(SIP_API_STRUCT));
                    memcpy(&sipToUpMsg, &sipTransPtr->sdMsg, sizeof(SIP_API_STRUCT));
                    sipToUpMsg.sipApiType = SIP_API_RES_MSG;
                    sipToUpMsg.sipApiMsg.sipMsg.sipStartLine.statusCode = SIP_TRANSACTION_TIMEOUT;
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipToUpMsg);
*///improve
                    memset(&sipToUpMsg, 0, sizeof(SIP_API_STRUCT));
                    sip_fill_msg_with_cr(&sipToUpMsg.sipApiMsg.sipMsg, &sipTransPtr->crMsg);
                    sipToUpMsg.sipApiType = SIP_API_RES_MSG;
                    sipToUpMsg.sipApiMsg.sipMsg.sipStartLine.statusCode = SIP_TRANSACTION_TIMEOUT;
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipToUpMsg);
                    sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                    return 1;
                }
            }
            break;
        case SIP_TRANS_STATE_PROCEEDING:
            if (rvCmd != SIP_COMMAND_IDLE)
            {
                sipTransPtr->rvCmd = SIP_COMMAND_IDLE;
                if ((rvCmd >= 200) & (rvCmd <= 699))
                {   // 100-699, resp. to TU
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
                    sipTransPtr->state = SIP_TRANS_STATE_COMPLETED;
                    sipTransPtr->timer = SIP_TIMER_K;
                    return 0;
                }
                else if (rvCmd == SIP_TRANSPORT_ERROR)
                {   // Transport error, inform TU
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
                    sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                    return 1;
                }
                else if ((rvCmd >= 100) & (rvCmd <= 199))
                {   // 1xx, 1xx to TU
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
                }
            }
            
            if ((SIP_TRANS_STATE_PROCEEDING == sipTransPtr->state) && (sipTransPtr->timer2 > 0))
            {
                if (--sipTransPtr->timer2 == 0)
                {// Timer E fires, send request
                    sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
//                    sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
                    sipTransPtr->retransTimes++;
                    sipTransPtr->timer2 = SIP_TIMER_T2;
                }
            }
            
            if ((SIP_TRANS_STATE_PROCEEDING == sipTransPtr->state) && (sipTransPtr->timer > 0))
            {
                if (--sipTransPtr->timer == 0)
                {// If timer F fires, inform TU
/*                    memset(&sipToUpMsg, 0, sizeof(SIP_API_STRUCT));
                    memcpy(&sipToUpMsg, &sipTransPtr->sdMsg, sizeof(SIP_API_STRUCT));
                    sipToUpMsg.sipApiType = SIP_API_RES_MSG;
                    sipToUpMsg.sipApiMsg.sipMsg.sipStartLine.statusCode = SIP_TRANSACTION_TIMEOUT;
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipToUpMsg);
*///improve
                    memset(&sipToUpMsg, 0, sizeof(SIP_API_STRUCT));
                    sip_fill_msg_with_cr(&sipToUpMsg.sipApiMsg.sipMsg, &sipTransPtr->crMsg);
                    sipToUpMsg.sipApiType = SIP_API_RES_MSG;
                    sipToUpMsg.sipApiMsg.sipMsg.sipStartLine.statusCode = SIP_TRANSACTION_TIMEOUT;
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipToUpMsg);
                    sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                    return 1;
                }
            }
            break;
        case SIP_TRANS_STATE_COMPLETED:
            if (sipTransPtr->timer > 0)
                sipTransPtr->timer--;
            
            if (sipTransPtr->timer == 0)
            {   // if timer K fires
                sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                return 1;
            }
            break;
        default:
            sipTransPtr->state = SIP_TRANS_STATE_IDLE;
            break;
    }
    
    return 0;
}

int sip_trans_clt_inv_proc(WORD transId)
{
    SIP_TRANSACTION     *sipTransPtr;
    SIP_USER            *sipUser;
    WORD                sdCmd;
    WORD                rvCmd;
    
    sipTransPtr = &sipTrans[transId];
    sdCmd = sipTransPtr->sdCmd;
    rvCmd = sipTransPtr->rvCmd;
    sipUser = &sipUsers.sipUsers[sipTransPtr->userIndex].sipUser;
    
    switch (sipTransPtr->state)
    {
        case SIP_TRANS_STATE_IDLE:
            if (sdCmd != SIP_COMMAND_IDLE)
            {
                sipTransPtr->sdCmd = SIP_COMMAND_IDLE;
                if ((sdCmd == SIP_METHOD_INVITE) || (sdCmd == SIP_METHOD_RE_INVITE))
                {   // INVITE from TU, INVITE sent
//                    sip_fill_cr_msg(&sipTransPtr->crMsg, &sipTransPtr->sdMsg);//improve
                    sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
//                    sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
                    sipTransPtr->timer = SIP_TIMER_B;
                    sipTransPtr->timer2 = SIP_TIMER_A;
                    sipTransPtr->state = SIP_TRANS_STATE_CALLING;
                }
                else
                    return 1;
            }
            break;
        case SIP_TRANS_STATE_CALLING:
            if (rvCmd != SIP_COMMAND_IDLE)
            {
                sipTransPtr->rvCmd = SIP_COMMAND_IDLE;
                if ((rvCmd >= 300) & (rvCmd <= 699))
                {   // 300-699, ACK sent, resp. to TU
                    sip_send_ack(&sipRecvMsg, sipTransPtr);
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
                    sipTransPtr->state = SIP_TRANS_STATE_COMPLETED;
                    sipTransPtr->timer = SIP_TIMER_D;
                    sipTransPtr->timer2 = 0;
                    return 0;
                }
                else if ((rvCmd >= 200) & (rvCmd <= 299))
                {   // 2xx, 2xx to TU
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
                    sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                    sipTransPtr->timer2 = 0;
                    return 1;
                }
                else if ((rvCmd >= 100) & (rvCmd <= 199))
                {   // 1xx, 1xx to TU
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
                    sipTransPtr->state = SIP_TRANS_STATE_PROCEEDING;
                    sipTransPtr->timer2 = 0;
                    sipTransPtr->timer = (7 * SIP_TIMER_T4);
                    return 0;
                }
                else if (rvCmd == SIP_TRANSPORT_ERROR)
                {   // transport error, inform TU
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
                    sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                    sipTransPtr->timer2 = 0;
                    return 1;
                }
            }
            
            if (sipTransPtr->timer2 > 0)
            {
                if (--sipTransPtr->timer2 == 0)
                {   // If timer A fires, reset A, INVITE sent
                    sip_transport_send_trans_msg(&sipTransPtr->transSdMsg);
//                    sip_transport_send_msg(&sipTransPtr->sdMsg);//improve
                    sipTransPtr->retransTimes++;
                    sipTransPtr->timer2 = sip_min((1 << sipTransPtr->retransTimes) * SIP_TIMER_E_INITIAL, SIP_TIMER_B);
                }
            }
            
            if ((SIP_TRANS_STATE_CALLING == sipTransPtr->state) && (sipTransPtr->timer > 0))
            {
                if (--sipTransPtr->timer == 0)
                {// If timer B fires, inform TU
/*                    memset(&sipToUpMsg, 0, sizeof(SIP_API_STRUCT));
                    memcpy(&sipToUpMsg, &sipTransPtr->sdMsg, sizeof(SIP_API_STRUCT));
                    sipToUpMsg.sipApiType = SIP_API_RES_MSG;
                    sipToUpMsg.sipApiMsg.sipMsg.sipStartLine.statusCode = SIP_TRANSACTION_TIMEOUT;
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipToUpMsg);
*///improve
                    memset(&sipToUpMsg, 0, sizeof(SIP_API_STRUCT));
                    sip_fill_msg_with_cr(&sipToUpMsg.sipApiMsg.sipMsg, &sipTransPtr->crMsg);
                    sipToUpMsg.sipApiType = SIP_API_RES_MSG;
                    sipToUpMsg.sipApiMsg.sipMsg.sipStartLine.statusCode = SIP_TRANSACTION_TIMEOUT;
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipToUpMsg);
                    sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                    return 1;
                }
            }
            break;
        case SIP_TRANS_STATE_PROCEEDING:
            if (rvCmd != SIP_COMMAND_IDLE)
            {
                sipTransPtr->rvCmd = SIP_COMMAND_IDLE;
                if ((rvCmd >= 300) & (rvCmd <= 699))
                {   // 300-699, ACK sent, resp. to TU
                    sip_send_ack(&sipRecvMsg, sipTransPtr);
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
                    sipTransPtr->state = SIP_TRANS_STATE_COMPLETED;
                    sipTransPtr->timer = SIP_TIMER_D;
                }
                else if ((rvCmd >= 200) & (rvCmd <= 299))
                {   // 2xx, 2xx to TU
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
                    sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                    return 1;
                }
                else if ((rvCmd >= 100) & (rvCmd <= 199))
                {   // 1xx, 1xx to TU
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
                }
            }

            if ((SIP_TRANS_STATE_PROCEEDING == sipTransPtr->state) && (sipTransPtr->timer > 0))
            {
                if (-- sipTransPtr->timer == 0)
                {
/*                    memset(&sipToUpMsg, 0, sizeof(SIP_API_STRUCT));
                    memcpy(&sipToUpMsg, &sipTransPtr->sdMsg, sizeof(SIP_API_STRUCT));
                    sipToUpMsg.sipApiType = SIP_API_RES_MSG;
                    sipToUpMsg.sipApiMsg.sipMsg.sipStartLine.statusCode = SIP_TRANSACTION_TIMEOUT;
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipToUpMsg);
*///improve
                    memset(&sipToUpMsg, 0, sizeof(SIP_API_STRUCT));
                    sip_fill_msg_with_cr(&sipToUpMsg.sipApiMsg.sipMsg, &sipTransPtr->crMsg);
                    sipToUpMsg.sipApiType = SIP_API_RES_MSG;
                    sipToUpMsg.sipApiMsg.sipMsg.sipStartLine.statusCode = SIP_TRANSACTION_TIMEOUT;
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipToUpMsg);
                    sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                    return 1;
                }
            }
            break;
        case SIP_TRANS_STATE_COMPLETED:     
            if (rvCmd != SIP_COMMAND_IDLE)
            {
                sipTransPtr->rvCmd = SIP_COMMAND_IDLE;
                if ((rvCmd >= 300) & (rvCmd <= 699))
                {   // 300-699, ACK sent
                    sip_send_ack(&sipRecvMsg, sipTransPtr);
                }
                else if (rvCmd == SIP_TRANSPORT_ERROR)
                {   // if transport error, inform TU
                    sipUser->recv_proc(transId, sipTransPtr->upPort, SIP_TRANSACTION_LAYER, &sipRecvMsg);
                    sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                    return 1;
                }
            }
            
            if (sipTransPtr->timer > 0)
                sipTransPtr->timer--;
            
            if (sipTransPtr->timer == 0)
            {   // if timer D fires
                sipTransPtr->state = SIP_TRANS_STATE_TERMINATED;
                return 1;
            }
            break;
        default:
            sipTransPtr->state = SIP_TRANS_STATE_IDLE;
            break;
    }
    
    return 0;
}

void sip_transaction_proc(WORD transid)
{
    switch (sipTrans[transid].mainState)
    {
        case SIP_TRANS_MAIN_STATE_INIT:
            sip_trans_init(transid);
            break;
        case SIP_TRANS_MAIN_STATE_SVR_NON_INV:
            switch (sip_trans_srv_non_inv_proc(transid))
            {
                case 0:
                    break;
                case 1:
                    sipTrans[transid].mainState = SIP_TRANS_MAIN_STATE_INIT;
                    sip_transaction_proc(transid);
                    break;
                default:
                    break;
            }
            break;
        case SIP_TRANS_MAIN_STATE_SVR_INV:
            switch (sip_trans_srv_inv_proc(transid))
            {
                case 0:
                    break;
                case 1:
                    sipTrans[transid].mainState = SIP_TRANS_MAIN_STATE_INIT;
                    sip_transaction_proc(transid);
                    break;
                default:
                    break;
            }
            break;
        case SIP_TRANS_MAIN_STATE_CLT_NON_INV:
            switch (sip_trans_clt_non_inv_proc(transid))
            {
                case 0:
                    break;
                case 1:
                    sipTrans[transid].mainState = SIP_TRANS_MAIN_STATE_INIT;
                    sip_transaction_proc(transid);
                    break;
                default:
                    break;
            }
            break;
        case SIP_TRANS_MAIN_STATE_CLT_INV:
            switch (sip_trans_clt_inv_proc(transid))
            {
                case 0:
                    break;
                case 1:
                    sipTrans[transid].mainState = SIP_TRANS_MAIN_STATE_INIT;
                    sip_transaction_proc(transid);
                    break;
                default:
                    break;
            }
            break;
        default:
            sipTrans[transid].mainState = SIP_TRANS_MAIN_STATE_INIT;
            break;
    }
}

int sip_msg_transport_to_transaction(SIP_API_STRUCT *recvMsg, WORD transId)
{
    SIP_TRANSACTION *sipTransPtr = &sipTrans[transId];
    
    if (recvMsg->sipApiType == SIP_API_TYPE_RESPONSE)
        sipTransPtr->rvCmd = recvMsg->sipApiMsg.sipMsg.sipStartLine.statusCode;
    else if (recvMsg->sipApiType == SIP_API_TYPE_REQUEST)
        sipTransPtr->rvCmd = recvMsg->sipApiMsg.sipMsg.sipStartLine.sipMethod;
    
    sip_transaction_proc(transId);
    
    return 0;
}

int sip_set_trans_send_cmd(SIP_TRANSACTION *trans, SIP_API_STRUCT *sipApiMsg)
{
    SIP_START_LINE      *startLine;
    
    startLine = &sipApiMsg->sipApiMsg.sipMsg.sipStartLine;
    
    if (sipApiMsg->sipApiType == SIP_API_REQ_MSG)
        trans->sdCmd = startLine->sipMethod;
    else if (sipApiMsg->sipApiType == SIP_API_RES_MSG)
        trans->sdCmd = startLine->statusCode;
    else
        return -1;
    
    return 0;
}

int sip_create_transaction(BYTE client, BYTE method, BYTE userIndex, WORD upPort, SIP_API_STRUCT *msg)
{
    WORD                i;
    WORD                transId = sipTransHead;
    SIP_TRANSACTION     *trans;


     if (msg == NULL)
     {
//         sip_trans_init(transId);
         return -1;
     }//improve

    if (transId>= SIP_MAX_NUM_OF_TRANS)
    {
        transId = 0;
    }
    
    for (i = 0; i < SIP_MAX_NUM_OF_TRANS; i++)
    {   
        trans = &sipTrans[transId];
        
        if (trans->flag != 0)
        {
            if (++transId >= SIP_MAX_NUM_OF_TRANS)
            {
                        transId = 0;
            }

            continue;
        }
        else
        {
            sip_trans_init(transId);
            trans->flag = 1;
            trans->client = client;
            trans->method = method;
            trans->userIndex = userIndex;
            trans->upPort = upPort;
/*            if (client == SIP_TRANS_SERVER)
            {
                if (msg == NULL)
                {
                    sip_trans_init(transId);
                    return -1;
                }

                sip_fill_cr_msg(&trans->crMsg, msg);
            }
*///improve
            sipTransHead = (transId+ 1) & SIP_MAX_NUM_OF_TRANS_1;
            
            if (client == SIP_TRANS_SERVER)
            {
                if (method == SIP_TRANS_NON_INVITE)
                    trans->mainState = SIP_TRANS_MAIN_STATE_SVR_NON_INV;
                else
                    trans->mainState = SIP_TRANS_MAIN_STATE_SVR_INV;
            }
            else
            {
                if (method == SIP_TRANS_NON_INVITE)
                    trans->mainState = SIP_TRANS_MAIN_STATE_CLT_NON_INV;
                else
                    trans->mainState = SIP_TRANS_MAIN_STATE_CLT_INV;

                if (msg->sipApiMsg.sipMsg.sipStartLine.sipMethod != SIP_METHOD_CANCEL)
                {
                    sip_create_trans_branch(transId, &msg->sipApiMsg.sipMsg.sipHdrVias.vias[msg->sipApiMsg.sipMsg.sipHdrVias.head].params.para[0]);
                    msg->sipApiMsg.sipMsg.sipHdrVias.vias[msg->sipApiMsg.sipMsg.sipHdrVias.head].params.paraNum++;
                }
            }
            trans->state = SIP_TRANS_STATE_IDLE;

            sip_fill_cr_msg(&trans->crMsg, msg);//improve

            return transId;
        }
    }
    
    return SIP_MAX_NUM_OF_TRANS;
}
