#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_msg.h"
#include "./include/sip_msg_parse.h"
#include "./include/sip_transaction.h"
#include "./include/sip_transport.h"
#include "./include/sip_debug.h"
#include "./include/sip_ua.h"
#include "./include/sip_ua_const.h"

BYTE sip_search_user_by_domain(SIP_URI *sipUri)
{
    BYTE    i;

    if (sipUri == NULL)
        return SIP_MAX_NUM_OF_USERS;

    for (i = 0; i < SIP_MAX_NUM_OF_USERS; i++)
    {   // Search for registered user
        if ((sipUsers.sipUsers[i].flag == 1) 
            && (strcmp(sipUsers.sipUsers[i].sipUser.domain, sipUri->host.addr.domain) == 0)
            && (strcmp(sipUsers.sipUsers[i].sipUser.userName, "SIP_UA") != 0))
            return i;
    }

    return SIP_MAX_NUM_OF_USERS;
}

int sip_match_ua_user_by_domain(SIP_API_STRUCT *sipApiMsg)
{
    pal_cg_struct    *cg;
    char                 *localDomain;
    char                 *destDomain;

/*    for (i = 0; i < SIP_MAX_NUM_OF_SIP_UA_USER; i++)
    {
        if (strcmp(sipSipUaUser[i].domain, domain) == 0)
            return i;
    }*/

    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;

    if ((cg = (pal_cg_struct *)pal_sip_find_cg(localDomain, destDomain)) == NULL)
        return -1;

    return 0;
}

BYTE sip_search_ua_user_by_domain(SIP_API_STRUCT *sipApiMsg)//SIP_URI sipUri
{
    BYTE    i;

    if (sipApiMsg == NULL)
        return SIP_MAX_NUM_OF_USERS;

    for (i = 0; i < SIP_MAX_NUM_OF_USERS; i++)
    {
        if ((sipUsers.sipUsers[i].flag == 1) 
            && (strcmp(sipUsers.sipUsers[i].sipUser.userName, "SIP_UA") == 0))
        {
            if (sip_match_ua_user_by_domain(sipApiMsg) < 0)//sipUri->host.addr.domain
                return SIP_MAX_NUM_OF_USERS;

            return i;
        }          
    }

    return SIP_MAX_NUM_OF_USERS;
}

BYTE sip_find_ua_user() 
{
    BYTE    i;

    for (i = 0; i < SIP_MAX_NUM_OF_USERS; i++)
    {
        if ((sipUsers.sipUsers[i].flag == 1) 
            && (strcmp(sipUsers.sipUsers[i].sipUser.userName, "SIP_UA") == 0))
            return i;
    }
       
    return SIP_MAX_NUM_OF_USERS;
}

BYTE sip_request_user_select(SIP_API_STRUCT *sipRecvMsg)
{
    BYTE        userIndex;
    SIP_URI     *sipUri = &sipRecvMsg->sipApiMsg.sipMsg.sipStartLine.requestUri;
    
    if ((userIndex = sip_search_user_by_domain(sipUri)) < SIP_MAX_NUM_OF_USERS)
        return userIndex;

    if ((userIndex = sip_search_ua_user_by_domain(sipRecvMsg)) < SIP_MAX_NUM_OF_USERS)//sipUri
        return userIndex;
    
    if ((sipUsers.proxyIndex < SIP_MAX_NUM_OF_USERS) 
        && (sipUsers.sipUsers[sipUsers.proxyIndex].flag == 1))
        return sipUsers.proxyIndex;
    
    return SIP_MAX_NUM_OF_USERS;
}

BYTE sip_response_user_select()
{
    if ((sipUsers.proxyIndex < SIP_MAX_NUM_OF_USERS) 
        && (sipUsers.sipUsers[sipUsers.proxyIndex].sipUser.proxyType == SIP_PROXY_TYPE_STATELESS))
        return sipUsers.proxyIndex;
    
    return SIP_MAX_NUM_OF_USERS;
}

int sip_method_api_conv(char *str, BYTE *method, BYTE flag)
{
    if ((str == NULL) || (method == NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_method_api_conv: point is NULL\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    if (flag == SIP_STR_TO_API)
    {
        if (strncmp(str, "REGISTER", 8) == 0)
            *method = SIP_METHOD_REGISTER;
        else if (strncmp(str, "INVITE", 6) == 0)
            *method = SIP_METHOD_INVITE;
        else if (strncmp(str, "ACK", 3) == 0)
            *method = SIP_METHOD_ACK;
        else if (strncmp(str, "CANCEL", 6) == 0)
            *method = SIP_METHOD_CANCEL;
        else if (strncmp(str, "BYE", 3) == 0)
            *method = SIP_METHOD_BYE;
        else if (strncmp(str, "OPTIONS", 7) == 0)
            *method = SIP_METHOD_OPTIONS;
        else if (strncmp(str, "INFO", 4) == 0)
            *method = SIP_METHOD_INFO;
        else if (strncmp(str, "PRACK", 5) == 0)
            *method = SIP_METHOD_PRACK;
        else if (strncmp(str, "UPDATE", 6) == 0)
            *method = SIP_METHOD_UPDATE;
        else if (strncmp(str, "REFER", 5) == 0)
            *method = SIP_METHOD_REFER;
        else if (strncmp(str, "re-INVITE", 9) == 0)
            *method = SIP_METHOD_RE_INVITE;
        else
            return -1;
        
        return 0;
    }
    else
    {
        switch (*method)
        {
            case SIP_METHOD_REGISTER:
                strcpy(str, "REGISTER");
                break;
            case SIP_METHOD_INVITE:
                strcpy(str, "INVITE");
                break;
            case SIP_METHOD_ACK:
                strcpy(str, "ACK");
                break;
            case SIP_METHOD_CANCEL:
                strcpy(str, "CANCEL");
                break;
            case SIP_METHOD_BYE:
                strcpy(str, "BYE");
                break;
            case SIP_METHOD_OPTIONS:
                strcpy(str, "OPTIONS");
                break;
            case SIP_METHOD_INFO:
                strcpy(str, "INFO");
                break;
            case SIP_METHOD_PRACK:
                strcpy(str, "PRACK");
                break;
            case SIP_METHOD_UPDATE:
                strcpy(str, "UPDATE");
                break;
            case SIP_METHOD_REFER:
                strcpy(str, "REFER");
                break;
            case SIP_METHOD_RE_INVITE:
                strcpy(str, "re-INVITE");
                break;
            default:
                return -1;
        }
        return 0;
    }
    
    return -1;
}

int sip_ver_api_conv(char *str, BYTE *ver, BYTE flag)
{
    if ((str == NULL) || (ver== NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_ver_api_conv: point is NULL\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    if (flag == SIP_STR_TO_API)
    {
        if (strcasecmp(str, "SIP/2.0") == 0)
             *ver = SIP_VERSION_2_0;
        else
        {
            sprintf((char *)sipAsciTempBuf, "Wrong version number\r\n");
            sip_log_err(sipAsciTempBuf);
            return -1;
        }
        return 0;
    }
    else
    {
        switch (*ver)
        {
            case SIP_VERSION_2_0:
                strcpy(str, "SIP/2.0");
                break;
            default:
                return -1;
        }
        return 0;
    }
    
    return -1;
}

int sip_mime_version_api_conv(char *str, BYTE *mimeVersion, BYTE flag)
{
    if ((str == NULL) || (mimeVersion == NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_mime_version_api_conv: point is NULL\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    if (flag == SIP_STR_TO_API)
    {
        if (strcmp(str, "1.0") == 0)
            *mimeVersion = SIP_MIME_VERSION_1_0;
        else
        {
            sprintf((char *)sipAsciTempBuf, "Wrong mime version number\r\n");
            sip_log_err(sipAsciTempBuf);
            return -1;
        }
    }
    else
    {
        switch(*mimeVersion)
        {
        case SIP_MIME_VERSION_1_0:
            strcpy(str, "1.0");
            break;
        default:
            return -1;
        }
    }

    return 0;
}

int sip_date_weekday_api_conv(char *str, BYTE *weekday, BYTE flag)
{
    if ((str == NULL) || (weekday == NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_date_weekday_api_conv: point is NULL\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    if (flag == SIP_STR_TO_API)
    {
        if (strcmp(str, "Sun") == 0)
            *weekday = SIP_DATE_WEEK_DAY_SUN;
        else if (strcmp (str, "Mon") == 0)
            *weekday = SIP_DATE_WEEK_DAY_MON;
        else if (strcmp (str, "Tue") == 0)
            *weekday = SIP_DATE_WEEK_DAY_TUE;
        else if (strcmp (str, "Wed") == 0)
            *weekday = SIP_DATE_WEEK_DAY_WED;
        else if (strcmp (str, "Thu") == 0)
            *weekday = SIP_DATE_WEEK_DAY_THU;
        else if (strcmp (str, "Fri") == 0)
            *weekday = SIP_DATE_WEEK_DAY_FRI;
        else if (strcmp (str, "Sat") == 0)
            *weekday = SIP_DATE_WEEK_DAY_SAT;
        else
        {
            sprintf((char *)sipAsciTempBuf, "Wrong date weekday\r\n");
            sip_log_err(sipAsciTempBuf);
            return -1;
        }
    }
    else
    {
        switch (*weekday)
        {
        case SIP_DATE_WEEK_DAY_SUN:
            strcpy(str, "Sun");
            break;
        case SIP_DATE_WEEK_DAY_MON:
            strcpy(str, "Mon");
            break;
        case SIP_DATE_WEEK_DAY_TUE:
            strcpy(str, "Tue");
            break;
        case SIP_DATE_WEEK_DAY_WED:
            strcpy(str, "Wed");
            break;
        case SIP_DATE_WEEK_DAY_THU:
            strcpy(str, "Thu");
            break;
        case SIP_DATE_WEEK_DAY_FRI:
            strcpy(str, "Fri");
            break;
        case SIP_DATE_WEEK_DAY_SAT:
            strcpy(str, "Sat");
            break;
        default:
            return -1;
        }
    }

    return 0;
}

int sip_date_month_api_conv(char *str, BYTE *month, BYTE flag)
{
    if ((str == NULL) || (month== NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_date_month_api_conv: point is NULL\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    if (flag == SIP_STR_TO_API)
    {
        if (strcmp(str, "Jan") == 0)
            *month = SIP_DATE_MONTH_JAN;
        else if (strcmp(str, "Feb") == 0)
            *month = SIP_DATE_MONTH_FEB;
        else if (strcmp(str, "Mar") == 0)
            *month = SIP_DATE_MONTH_MAR;
        else if (strcmp(str, "Apr") == 0)
            *month = SIP_DATE_MONTH_APR;
        else if (strcmp(str, "May") == 0)
            *month = SIP_DATE_MONTH_MAY;
        else if (strcmp(str, "Jun") == 0)
            *month = SIP_DATE_MONTH_JUN;
        else if (strcmp(str, "Jul") == 0)
            *month = SIP_DATE_MONTH_JUL;
        else if (strcmp(str, "Aug") == 0)
            *month = SIP_DATE_MONTH_AUG;
        else if (strcmp(str, "Sep") == 0)
            *month = SIP_DATE_MONTH_SEP;
        else if (strcmp(str, "Oct") == 0)
            *month = SIP_DATE_MONTH_OCT;
        else if (strcmp(str, "Nov") == 0)
            *month = SIP_DATE_MONTH_NOV;
        else if (strcmp(str, "Dec") == 0)
            *month = SIP_DATE_MONTH_DEC;
        else
        {
            sprintf((char *)sipAsciTempBuf, "Wrong date month\r\n");
            sip_log_err(sipAsciTempBuf);
            return -1;
        }
    }
    else
    {
        switch(*month)
        {
        case SIP_DATE_MONTH_JAN:
            strcpy(str, "Jan");
            break;
        case SIP_DATE_MONTH_FEB:
            strcpy(str, "Feb");
            break;
        case SIP_DATE_MONTH_MAR:
            strcpy(str, "Mar");
            break;
        case SIP_DATE_MONTH_APR:
            strcpy(str, "Apr");
            break;
        case SIP_DATE_MONTH_MAY:
            strcpy(str, "May");
            break;
        case SIP_DATE_MONTH_JUN:
            strcpy(str, "Jun");
            break;
        case SIP_DATE_MONTH_JUL:
            strcpy(str, "Jul");
            break;
        case SIP_DATE_MONTH_AUG:
            strcpy(str, "Aug");
            break;
        case SIP_DATE_MONTH_SEP:
            strcpy(str, "Sep");
            break;
        case SIP_DATE_MONTH_OCT:
            strcpy(str, "Oct");
            break;
        case SIP_DATE_MONTH_NOV:
            strcpy(str, "Nov");
            break;
        case SIP_DATE_MONTH_DEC:
            strcpy(str, "Dec");
            break;
        default:
            return -1;
        }
    }

    return 0;
}

int sip_date_type_api_conv(char *str, BYTE *dateType, BYTE flag)
{
    if ((str == NULL) || (dateType == NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_date_type_api_conv: point is NULL\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    if (flag == SIP_STR_TO_API)
    {
        if (strcmp(str, "GMT") == 0)
            *dateType = SIP_DATE_TYPE_GMT;
        else
        {
            sprintf((char *)sipAsciTempBuf, "Wrong date month\r\n");
             sip_log_err(sipAsciTempBuf);
            return -1;
        }
    }
    else
    {
        switch (*dateType)
        {
         case SIP_DATE_TYPE_GMT:
             strcpy(str, "GMT");
             break;
         default:
             return -1;
        }
    }

    return 0;
}

int sip_proto_api_conv(char *str, BYTE *proto, BYTE flag)
{
    if ((str == NULL) || (proto == NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_proto_api_conv: point is NULL\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    if (flag == SIP_STR_TO_API)
    {
        if (strcasecmp(str, "UDP") == 0)
             *proto = SIP_API_PROTO_UDP;
        else if (strcasecmp(str, "TCP") == 0)
             *proto = SIP_API_PROTO_TCP;
        else if (strcasecmp(str, "SCTP") == 0)
             *proto = SIP_API_PROTO_SCTP;
        else
        {
            sprintf((char *)sipAsciTempBuf, "Wrong protocol type\r\n");
            sip_log_err(sipAsciTempBuf);
            return -1;
        }
        return 0;
    }
    else
    {
        switch (*proto)
        {
            case SIP_API_PROTO_UDP:
                strcpy(str, "UDP");
                break;
            case SIP_API_PROTO_TCP:
                strcpy(str, "TCP");
                break;
            case SIP_API_PROTO_SCTP:
                strcpy(str, "SCTP");
                break;
            default:
                return -1;
        }
        return 0;
    }
    
    return -1;
}

int sip_uri_type_api_conv(char *str, BYTE *uriType, BYTE flag)
{
    if ((str == NULL) || (uriType == NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_uri_type_api_conv: point is NULL\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    if (flag == SIP_STR_TO_API)
    {
        if (strncasecmp (str, "SIPS", 4) == 0)
             *uriType = SIP_URI_TYPE_SIPS;
        else if (strncasecmp (str, "SIP", 3) == 0)
             *uriType = SIP_URI_TYPE_SIP;
        else if (strncasecmp (str, "TEL", 3) == 0)
             *uriType = SIP_URI_TYPE_TEL;
        else
        {
            sprintf((char *)sipAsciTempBuf, "Unsupported URI type\r\n");
            sip_log_err(sipAsciTempBuf);
            return -1;
        }
        return 0;
    }
    else
    {
        switch (*uriType)
        {
            case SIP_URI_TYPE_SIP:
                strcpy(str, "SIP");
                break;
            case SIP_URI_TYPE_SIPS:
                strcpy(str, "SIPS");
                break;
            case SIP_URI_TYPE_TEL:
                strcpy(str, "TEL");
                break;
            default:
                return -1;
        }
        return 0;
    }
    
    return -1;
}

int sip_accept_type_api_conv(char *str, BYTE *acceptType, BYTE flag)
{
    if ((str == NULL) || (acceptType == NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_accept_type_api_conv: point is NULL\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    if (flag == SIP_STR_TO_API)
    {
        if (strcasecmp(str, "application") == 0)
                *acceptType = SIP_ACCEPT_TYPE_APPLICATION;
        else if (strcasecmp(str, "multipart") == 0)
            *acceptType = SIP_ACCEPT_TYPE_MULTIPART;
        else if (strcasecmp(str, "*") == 0)
            *acceptType = SIP_ACCEPT_TYPE_WILDCARD;
        else
        {
            sprintf((char *)sipAsciTempBuf, "Wrong accept type\r\n");
            sip_log_err(sipAsciTempBuf);
            return -1;
        }
        return 0;
    }
    else
    {
        switch (*acceptType)
        {
            case SIP_ACCEPT_TYPE_APPLICATION:
                strcpy(str, "application");
                break;
            case SIP_ACCEPT_TYPE_MULTIPART:
                strcpy(str, "multipart");
                break;
            case SIP_ACCEPT_TYPE_WILDCARD:
                strcpy(str, "*");
                break;
            default:
                return -1;
        }
        return 0;
    }
    
    return -1;
}

int sip_accept_sub_type_api_conv(char *str, BYTE *acceptSubType, BYTE flag)
{
    if ((str == NULL) || (acceptSubType == NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_accept_sub_type_api_conv: point is NULL\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    if (flag == SIP_STR_TO_API)
    {
        if (strcasecmp(str, "sdp") == 0)
                *acceptSubType = SIP_ACCEPT_SUB_TYPE_SDP;
        else if (strcasecmp(str, "isup") == 0)
            *acceptSubType = SIP_ACCEPT_SUB_TYPE_ISUP;
        else if (strcasecmp(str, "mixed") == 0)
            *acceptSubType = SIP_ACCEPT_SUB_TYPE_MIXED;
        else if (strcasecmp(str, "*") == 0)
            *acceptSubType = SIP_ACCEPT_SUB_TYPE_WILDCARD;
            else
            {
                sprintf((char *)sipAsciTempBuf, "Wrong accept sub type\r\n");
                sip_log_err(sipAsciTempBuf);
                return -1;
            }

        return 0;
    }
    else
    {
        switch (*acceptSubType)
        {
            case SIP_ACCEPT_SUB_TYPE_SDP:
                strcpy(str, "sdp");
                break;
            case SIP_ACCEPT_SUB_TYPE_ISUP:
                strcpy(str, "isup");
                break;
            case SIP_ACCEPT_SUB_TYPE_MIXED:
                strcpy(str, "mixed");
                break;
            case SIP_ACCEPT_SUB_TYPE_WILDCARD:
                strcpy(str, "*");
                break;
            default:
                return -1;
        }
        return 0;
    }
    
    return -1;
}

int sip_accept_encoding_api_conv(char *str, BYTE *acceptEncoding, BYTE flag)
{
    if ((str == NULL) || (acceptEncoding == NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_accept_encoding_api_conv: point is NULL\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    if (flag == SIP_STR_TO_API)
    {
        if (strcasecmp(str, "identity") == 0)
            *acceptEncoding = SIP_ACCEPT_ENCODING_IDENTITY;
        else if (strcasecmp(str, "gzip") == 0)
            *acceptEncoding = SIP_ACCEPT_ENCODING_GZIP;
        else if (strcasecmp(str, "tar") == 0)
            *acceptEncoding = SIP_ACCEPT_ENCODING_TAR;
        else
        {
                sprintf((char *)sipAsciTempBuf, "Wrong accept encoding\r\n");
                sip_log_err(sipAsciTempBuf);
                return -1;
        }

        return 0;
    }
    else
    {
        switch (*acceptEncoding)
        {
        case SIP_ACCEPT_ENCODING_IDENTITY:
            strcpy(str, "identity");
            break;
        case SIP_ACCEPT_ENCODING_GZIP:
            strcpy(str, "gzip");
            break;
           case SIP_ACCEPT_ENCODING_TAR:
               strcpy(str, "tar");
               break;
        default:
            return -1;
        }

        return 0;
    }

    return -1;
}

int sip_accept_language_api_conv(char *str, BYTE *acceptLanguage, BYTE flag) 
{
    if ((str == NULL) || (acceptLanguage == NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_accept_language_api_conv: point is NULL\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    if (flag == SIP_STR_TO_API)
    {
        if (strcasecmp(str, "en") == 0)
            *acceptLanguage = SIP_ACCEPT_LANGUAGE_EN;
        else
        {
                sprintf((char *)sipAsciTempBuf, "Wrong accept language\r\n");
                sip_log_err(sipAsciTempBuf);
                return -1;          
        }
    }
    else
    {
        switch (*acceptLanguage)
        {
        case SIP_ACCEPT_LANGUAGE_EN:
            strcpy(str, "en");
            break;
        default:
            return -1;
        }
    }

    return 0;
}

int sip_content_type_api_conv(char *str, BYTE *contentType, BYTE flag)
{
    if ((str == NULL) || (contentType == NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_content_type_api_conv: point is NULL\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    if (flag == SIP_STR_TO_API)
    {
        if (strcasecmp(str, "application") == 0)
            *contentType = SIP_CONTENT_TYPE_APPLICATION;
        else if (strcasecmp(str, "multipart") == 0)
            *contentType = SIP_CONTENT_TYPE_MULTIPART;
        else if (strcasecmp(str, "text") == 0)
            *contentType = SIP_CONTENT_TYPE_TEXT;
        else if (strcasecmp(str, "image") == 0)
            *contentType = SIP_CONTENT_TYPE_IMAGE;
        else if (strcasecmp(str, "audio") == 0)
            *contentType = SIP_CONTENT_TYPE_AUDIO;
        else if (strcasecmp(str, "vedio") == 0)
            *contentType = SIP_CONTENT_TYPE_VEDIO;
        else
        {
            sprintf((char *)sipAsciTempBuf, "Wrong content type\r\n");
            sip_log_err(sipAsciTempBuf);
            return -1;
        }
        return 0;
     }
     else
     {
         switch (*contentType)
         {
         case SIP_CONTENT_TYPE_APPLICATION:
             strcpy(str, "application");
             break;
         case SIP_CONTENT_TYPE_MULTIPART:
             strcpy(str, "multipart");
             break;
         case SIP_CONTENT_TYPE_TEXT:
             strcpy(str, "text");
             break;
         case SIP_CONTENT_TYPE_IMAGE:
             strcpy(str, "image");
             break;
         case SIP_CONTENT_TYPE_AUDIO:
             strcpy(str, "audio");
             break;
         case SIP_CONTENT_TYPE_VEDIO:
             strcpy(str, "vedio");
             break;
         default:
             return -1;
      }
      return 0;
     }
    
     return -1;
}

int sip_content_sub_type_api_conv(char *str, BYTE *contentSubType, BYTE flag)
{
    if ((str == NULL) || (contentSubType == NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_content_sub_type_api_conv: point is NULL\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    if (flag == SIP_STR_TO_API)
    {
        if (strcasecmp(str, "sdp") == 0)
            *contentSubType = SIP_CONTENT_SUB_TYPE_SDP;
        else if (strcasecmp(str, "isup") == 0)
            *contentSubType = SIP_CONTENT_SUB_TYPE_ISUP;
        else if (strcasecmp(str, "mixed") == 0)
            *contentSubType = SIP_CONTENT_SUB_TYPE_MIXED;
        else if (strcasecmp(str, "message") == 0)
            *contentSubType = SIP_CONTENT_SUB_TYPE_MESSAGE;
        else if (strcasecmp(str, "signed") == 0)
            *contentSubType = SIP_CONTENT_SUB_TYPE_SIGNED;
        else if (strcasecmp(str, "pkcs7-mime") == 0)
            *contentSubType = SIP_CONTENT_SUB_TYPE_PKCS7_MIME;
        else
        {
            sprintf((char *)sipAsciTempBuf, "Wrong content sub type\r\n");
            sip_log_err(sipAsciTempBuf);
            return -1;
        }

        return 0;
    }
    else
    {
        switch (*contentSubType)
        {
        case SIP_CONTENT_SUB_TYPE_SDP:
            strcpy(str, "sdp");
            break;
        case SIP_CONTENT_SUB_TYPE_ISUP:
            strcpy(str, "isup");
            break;
        case SIP_CONTENT_SUB_TYPE_MIXED:
            strcpy(str, "mixed");
            break;
        case SIP_CONTENT_SUB_TYPE_MESSAGE:
            strcpy(str, "message");
            break;
        case SIP_CONTENT_SUB_TYPE_SIGNED:
            strcpy(str, "signed");
            break;
        case SIP_CONTENT_SUB_TYPE_PKCS7_MIME:
            strcpy(str, "pkcs7-mime");
            break;
        default:
            return -1;
        }
        return 0;
    }
    return -1;
}

int sip_content_disposition_api_conv(char *str, BYTE *contentDisposition, BYTE flag)    
{
    if ((str == NULL) || (contentDisposition == NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_content_disposition_api_conv: point is NULL\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    if (flag == SIP_STR_TO_API)
    {
        if (strcasecmp(str, "signal") == 0)
        {
            *contentDisposition = SIP_CONTENT_DISPOSITION_SIGNAL;
        }
        else
        {
            sprintf((char *)sipAsciTempBuf, "Wrong content disposition\r\n");
            sip_log_err(sipAsciTempBuf);
            return -1;
        }
    }
    else
    {
        switch (*contentDisposition)
        {
        case SIP_CONTENT_DISPOSITION_SIGNAL:
            strcpy(str, "signal");
            break;
        default:
            return -1;
        }
    }

    return 0;
}

int sip_content_encoding_api_conv(char *str, BYTE *contentEncoding, BYTE flag)
{
    if ((str == NULL) || (contentEncoding == NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_content_encoding_api_conv: point is NULL\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    if (flag == SIP_STR_TO_API)
    {
        if (strcasecmp(str, "identity") == 0)
            *contentEncoding = SIP_CONTENT_ENCODING_IDENTITY;
        else if (strcasecmp(str, "gzip") == 0)
            *contentEncoding = SIP_CONTENT_ENCODING_GZIP;
        else if (strcasecmp(str, "tar") == 0)
            *contentEncoding = SIP_CONTENT_ENCODING_TAR;
        else
        {
            sprintf((char *)sipAsciTempBuf, "Wrong content encoding\r\n");
            sip_log_err(sipAsciTempBuf);
            return -1;
        }
    }
    else
    {
        switch (*contentEncoding)
        {
        case SIP_CONTENT_ENCODING_IDENTITY:
            strcpy(str, "identity");
            break;
        case SIP_CONTENT_ENCODING_GZIP:
            strcpy(str, "gzip");
            break;
        case SIP_CONTENT_ENCODING_TAR:
            strcpy(str, "tar");
            break;
        default:
            return -1;
        }
    }
    return 0;
}

int sip_content_language_api_conv(char *str, BYTE *contentLanguage, BYTE flag)
{
    if ((str == NULL) || (contentLanguage == NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_content_language_api_conv: point is NULL\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    if (flag == SIP_STR_TO_API)
    {
        if (strcasecmp(str, "en") == 0)
            *contentLanguage = SIP_CONTENT_LANGUAGE_EN;
        else
        {
            sprintf((char *)sipAsciTempBuf, "Wrong content language\r\n");
            sip_log_err(sipAsciTempBuf);
            return -1;          
        }
    }
    else
    {
        switch(*contentLanguage)
        {
        case SIP_CONTENT_LANGUAGE_EN:
            strcpy(str, "en");
            break;
        default:
            return -1;
        }
    }

    return 0;
}

int sip_allow_api_conv(char *str, BYTE *allowMethod, BYTE flag)
{
    if ((str == NULL) || (allowMethod == NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_allow_api_conv: point is NULL\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    if (flag == SIP_STR_TO_API)
    {
        if (strcmp(str, "REGISTER") == 0)
            *allowMethod = SIP_METHOD_REGISTER;
        else if (strcmp(str, "INVITE") == 0)
            *allowMethod = SIP_METHOD_INVITE;
        else if (strcmp(str, "ACK") == 0)
            *allowMethod = SIP_METHOD_ACK;
        else if (strcmp(str, "CANCEL") == 0)
            *allowMethod = SIP_METHOD_CANCEL;
        else if (strcmp(str, "BYE") == 0)
            *allowMethod = SIP_METHOD_BYE;
        else if (strcmp(str, "OPTIONS") == 0)
            *allowMethod = SIP_METHOD_OPTIONS;
        else if (strcmp(str, "INFO") == 0)
            *allowMethod = SIP_METHOD_INFO;
        else if (strcmp(str, "PRACK") == 0)
            *allowMethod = SIP_METHOD_PRACK;
        else if (strcmp(str, "UPDATE") == 0)
            *allowMethod = SIP_METHOD_UPDATE;
        else if (strcmp(str, "REFER") == 0)
            *allowMethod = SIP_METHOD_REFER;
	 else
	 	return -2;
    }
    else
    {
        switch (*allowMethod)
        {
        case SIP_METHOD_REGISTER:
            strcpy(str, "REGISTER");
            break;
        case SIP_METHOD_INVITE:
            strcpy(str, "INVITE");
            break;
        case SIP_METHOD_ACK:
            strcpy(str, "ACK");
            break;
        case SIP_METHOD_CANCEL:
            strcpy(str, "CANCEL");
            break;
        case SIP_METHOD_BYE:
            strcpy(str, "BYE");
            break;
        case SIP_METHOD_OPTIONS:
            strcpy(str, "OPTIONS");
            break;
        case SIP_METHOD_INFO:
            strcpy(str, "INFO");
            break;
        case SIP_METHOD_PRACK:
            strcpy(str, "PRACK");
            break;
        case SIP_METHOD_UPDATE:
            strcpy(str, "UPDATE");
            break;
        case SIP_METHOD_REFER:
            strcpy(str, "REFER");
            break;
        default:
            return -1;//return -1;
        }
    }

    return 0;
}

int sip_option_tag_api_conv(char *str, BYTE *option, BYTE flag)
{
    if ((str == NULL) || (option == NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_option_tag_api_conv: point is NULL\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    if (flag == SIP_STR_TO_API)
    {
        if (strcasecmp(str, "100rel") == 0)
            *option = SIP_OPTION_TAG_100_REL;       
        else if (strcasecmp(str, "foo") == 0)
            *option = SIP_OPTION_TAG_FOO;
        else
            return 0;
    }
    else
    {
        switch (*option)
        {
         case SIP_OPTION_TAG_100_REL:
            strcpy(str, "100rel");
            break;
         case SIP_OPTION_TAG_FOO:
            strcpy(str, "foo");
            break;
         default:
            return -1;
        }
    }

    return 0;
}

int sip_recv_msg_handling(char *msg, WORD len, int tcpSockIndex)
{
    char        *nextHeader;
    BYTE        user;
    WORD        transId;
    SIP_ENTITY  *sipEntity;
    
    sip_util_replace_all_lws(msg);
    
    if (sip_msg_start_line_parse(&sipRecvMsg, msg, &nextHeader) < 0)
        return -1;
    
    if (sip_msg_headers_parse(&sipRecvMsg, nextHeader, &nextHeader) < 0)
        return -1;
    
    sipEntity = &sipRecvMsg.sipApiMsg.sipMsg.sipEntity;
    
    if (nextHeader[0] == '\0' || nextHeader[1] == '\0' || nextHeader[2] == '\0')
    {    // No body found
        if (sipEntity->sipHdrContentLength > 0)
            return -1;
    }
    else if (sipEntity->sipHdrContentLength > 0)
    {
        if ((nextHeader[0] == '\r') && (nextHeader[1] == '\n'))
            nextHeader = nextHeader + 2;
        else
            nextHeader = nextHeader + 1;
            
        if (sip_body_parse(&sipRecvMsg, nextHeader, len - (nextHeader - msg - 2)) < 0)
        {
            sprintf((char *)sipAsciTempBuf, "sip_recv_msg_handling:sip_body_parse failed\r\n");
            sip_log_err(sipAsciTempBuf);
            return -1;
        }
    }
    
    if (sipRecvMsg.sipApiType == SIP_API_REQ_MSG)
    {
        if (sipRecvMsg.sipApiMsg.sipMsg.sipStartLine.sipMethod == SIP_METHOD_OPTIONS)
        {
            sip_send_option_rsp(&sipRecvMsg);
            return 0;
        }
    	
        if ((transId = sip_request_match_server_trans(&sipRecvMsg)) >= SIP_MAX_NUM_OF_TRANS)
        {
            if ((user = sip_request_user_select(&sipRecvMsg)) < SIP_MAX_NUM_OF_USERS)
                sipUsers.sipUsers[user].sipUser.recv_proc(SIP_NULL_TRANS_ID, SIP_NULL_UP_PORT, SIP_TRANSPORT_LAYER, &sipRecvMsg);
            else
            {
//                sip_process_invalid_req(&sipRecvMsg);
                if (sipRecvMsg.sipApiMsg.sipMsg.sipStartLine.sipMethod == SIP_METHOD_CANCEL)
                {
                    sip_send_call_not_exit_rsp(&sipRecvMsg);
                }
                else
                {
                    sip_send_not_find_rsp(&sipRecvMsg);
                }
                return -1;
            }
        }
        else
            sip_msg_transport_to_transaction(&sipRecvMsg, transId);
    }
    else
    {
        if ((transId = sip_response_match_client_trans(&sipRecvMsg)) >= SIP_MAX_NUM_OF_TRANS)
        {
            if ((sipRecvMsg.sipApiMsg.sipMsg.sipHdrCseq.method == SIP_METHOD_INVITE) 
                 && (sipRecvMsg.sipApiMsg.sipMsg.sipStartLine.statusCode == 200) 
                 && ((user = sip_find_ua_user(&sipRecvMsg)) < SIP_MAX_NUM_OF_USERS))
            {
                if (sip_response_match_ua_dialog(&sipRecvMsg) < SIP_UA_MAX_NUM_OF_DIALOG)
                {
                    sipUsers.sipUsers[user].sipUser.recv_proc(SIP_NULL_TRANS_ID, SIP_NULL_UP_PORT, SIP_TRANSPORT_LAYER, &sipRecvMsg);
                    return 0;
                }
                else
                {
                    sprintf((char *)sipAsciTempBuf, "sip_recv_msg_handling:invite 200 can not find dialog failed\r\n");
                    sip_log_err(sipAsciTempBuf);
                }
            }
                     
            if ((user = sip_response_user_select()) < SIP_MAX_NUM_OF_USERS)
                sipUsers.sipUsers[user].sipUser.recv_proc(SIP_NULL_TRANS_ID, SIP_NULL_UP_PORT, SIP_TRANSPORT_LAYER, &sipRecvMsg);
            else
                return -1;
        }
        else
            sip_msg_transport_to_transaction(&sipRecvMsg, transId);
    }
    
    return 0;
}

/*  The upper layer uses this function to send sip message to the peer
    sipTransId: destination SIP transcation ID the UP message will be sent to, if unknown, it should be set to 0xFFFF
    upPort: source UP port the message is sent from
    transFlag: indicates whether this message will be sent within SIP transaction layer (stateful proxy or user agent),
                or directly goes to the SIP transport layer (stateless proxy)
    sipApiMsg: a pointer pointing to the actual struct of the message to be sent to the SIP module
    if succeeds, returns sip_port, otherwise return a negative value
    if succeeds, and no sip_port is maintained for this message, returns 0xFFFF
*/

void sip_fill_msg_with_cr(SIP_MSG *sipMsg, SIP_CR_MSG *sipCrMsg)
{
    if ((sipMsg == NULL) || (sipCrMsg == NULL))
    {
        return;
    }

    memcpy(&sipMsg->sipStartLine, &sipCrMsg->sipCrStartLine, sizeof(SIP_START_LINE));
    memcpy(&sipMsg->sipHdrTo, &sipCrMsg->sipCrHdrTo, sizeof(SIP_HDR_TO));
    memcpy(&sipMsg->sipHdrFrom, &sipCrMsg->sipCrHdrFrom, sizeof(SIP_HDR_FROM));
    memcpy(&sipMsg->sipHdrCseq, &sipCrMsg->sipCrHdrCseq, sizeof(SIP_HDR_CSEQ));
    memcpy(&sipMsg->sipHdrCallId, &sipCrMsg->sipCrHdrCallId, sizeof(SIP_HDR_CALL_ID));
    sipMsg->sipHdrVias.num = 1;
    sipMsg->sipHdrVias.head = 1;
    memcpy(&sipMsg->sipHdrVias.vias[1], &sipCrMsg->sipCrHdrVia, sizeof(SIP_HDR_VIA));
}

void sip_fill_cr_msg(SIP_CR_MSG *sipCrMsg, SIP_API_STRUCT *sipApiMsg)
{
    SIP_MSG    *sipMsg;
	BYTE       head;

    if ((sipCrMsg == NULL) || (sipApiMsg == NULL))
    {
        return;
    }

    memcpy(&sipCrMsg->sipTransAddr, &sipApiMsg->sipTransAddr, sizeof(SIP_TRANSPORT_ADDR));

    sipMsg = &sipApiMsg->sipApiMsg.sipMsg;

    memcpy(&sipCrMsg->sipCrStartLine, &sipMsg->sipStartLine, sizeof(SIP_START_LINE));
    memcpy(&sipCrMsg->sipCrHdrTo, &sipMsg->sipHdrTo, sizeof(SIP_HDR_TO));
    memcpy(&sipCrMsg->sipCrHdrFrom, &sipMsg->sipHdrFrom, sizeof(SIP_HDR_FROM));
    memcpy(&sipCrMsg->sipCrHdrCseq, &sipMsg->sipHdrCseq, sizeof(SIP_HDR_CSEQ));
    memcpy(&sipCrMsg->sipCrHdrCallId, &sipMsg->sipHdrCallId, sizeof(SIP_HDR_CALL_ID));
    head = sipMsg->sipHdrVias.head;
    memcpy(&sipCrMsg->sipCrHdrVia, &sipMsg->sipHdrVias.vias[head], sizeof(SIP_HDR_VIA));
}

void sip_fill_allow_header(SIP_API_STRUCT *sipApiMsg)
{
    SIP_MSG     *sdMsg;
    BYTE            num = 0;

    if (sipApiMsg == NULL)
    {
        return;
    }

    sdMsg = &sipApiMsg->sipApiMsg.sipMsg;

    if (sipApiMsg->sipApiType == SIP_API_REQ_MSG)
    {
        sipApiMsg->sipApiMsg.sipMsg.sipGenHdrFlag[0] |= SIP_HDR_ALLOW_MASK;

        sdMsg->sipHdrAllow.allowMethod[num++] = SIP_METHOD_REGISTER;
        sdMsg->sipHdrAllow.allowMethod[num++] = SIP_METHOD_INVITE;
        sdMsg->sipHdrAllow.allowMethod[num++] = SIP_METHOD_ACK;
        sdMsg->sipHdrAllow.allowMethod[num++] = SIP_METHOD_CANCEL;
        sdMsg->sipHdrAllow.allowMethod[num++] = SIP_METHOD_BYE;
        sdMsg->sipHdrAllow.allowMethod[num++] = SIP_METHOD_OPTIONS;
        sdMsg->sipHdrAllow.allowMethod[num++] = SIP_METHOD_UPDATE;

        sdMsg->sipHdrAllow.num = num;

        return;
    }
    else
    {
        if ((sipApiMsg->sipApiMsg.sipMsg.sipStartLine.statusCode > 100) 
             && (sipApiMsg->sipApiMsg.sipMsg.sipStartLine.statusCode < 300))
        {
            sdMsg->sipHdrAllow.allowMethod[num++] = SIP_METHOD_REGISTER;
            sdMsg->sipHdrAllow.allowMethod[num++] = SIP_METHOD_INVITE;
            sdMsg->sipHdrAllow.allowMethod[num++] = SIP_METHOD_ACK;
            sdMsg->sipHdrAllow.allowMethod[num++] = SIP_METHOD_CANCEL;
            sdMsg->sipHdrAllow.allowMethod[num++] = SIP_METHOD_BYE;
            sdMsg->sipHdrAllow.allowMethod[num++] = SIP_METHOD_OPTIONS;
            sdMsg->sipHdrAllow.allowMethod[num++] = SIP_METHOD_INFO;

            sdMsg->sipHdrAllow.num = num;
        }

        return;
    }
}

int sip_send_msg(WORD sipTransId, WORD upPort, BYTE transFlag, SIP_API_STRUCT *sipApiMsg)
{
    SIP_TRANSACTION     *trans;
    
    if (transFlag == SIP_TRANSACTION_LAYER)
    {
        if (sipTransId >= SIP_MAX_NUM_OF_TRANS)
            return -1;
        
        trans = &sipTrans[sipTransId];

	sip_fill_allow_header(sipApiMsg);

        if (sip_transport_encode_trans_msg(trans, sipApiMsg) < 0)
        {
             sprintf((char *)sipAsciTempBuf, "sip_send_msg:encode sip msg failed\r\n");
             sip_log_err(sipAsciTempBuf);
             return -1;
        }

//        memcpy((BYTE *)&trans->sdMsg, (BYTE *)sipApiMsg, sizeof(SIP_API_STRUCT));   // backup, for retransmission
        sip_set_trans_send_cmd(trans, sipApiMsg);
        sip_transaction_proc(sipTransId);
    }
    else
    {
        sip_transport_send_msg(sipApiMsg);
    }
    
    return 0;
}

int sip_send_ack(SIP_API_STRUCT *ackMsg, SIP_TRANSACTION *trans)
{
    SIP_MSG     *sdMsg = &sipSendMsg.sipApiMsg.sipMsg;

    if ((ackMsg == NULL) || (trans == NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_send_ack:msg or transaction is NULL\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    memset((BYTE *) &sipSendMsg, 0, sizeof(SIP_API_STRUCT));
    memcpy((BYTE *) &sipSendMsg, (BYTE *) ackMsg, sizeof(SIP_API_STRUCT));
    memcpy((BYTE *) &sdMsg->sipStartLine, (BYTE *) &trans->crMsg.sipCrStartLine, sizeof(SIP_START_LINE));
//    memcpy((BYTE *) &sdMsg->sipStartLine, (BYTE *) &srcMsg->sipStartLine, sizeof(SIP_START_LINE));
    
    sipSendMsg.sipApiType = SIP_API_REQ_MSG;
    sdMsg->sipStartLine.sipMethod = SIP_METHOD_ACK;
    sdMsg->sipHdrCseq.method = SIP_METHOD_ACK;
    sdMsg->sipEntity.sipHdrContentLength = 0;
    sdMsg->sipGenHdrFlag[0] = SIP_HDR_CALL_ID_MASK | SIP_HDR_CSEQ_MASK |
                              SIP_HDR_FROM_MASK | SIP_HDR_TO_MASK | SIP_HDR_VIA_MASK;

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

    sip_transport_send_msg(&sipSendMsg);
    
    return 0;
}

int sip_send_100(SIP_CR_MSG *ackMsg, SIP_TRANSACTION *trans)
{
    SIP_MSG     *sdMsg = &sipSendMsg.sipApiMsg.sipMsg;

    if ((ackMsg == NULL) || (trans == NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_send_100:msg or transaction is NULL\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    memset((BYTE *) &sipSendMsg, 0, sizeof(SIP_API_STRUCT));
    memcpy((BYTE *)&sipSendMsg.sipTransAddr, &ackMsg->sipTransAddr, sizeof(SIP_TRANSPORT_ADDR));
    sip_fill_msg_with_cr(sdMsg, ackMsg);
    
    sipSendMsg.sipApiType = SIP_API_RES_MSG;
    sdMsg->sipStartLine.statusCode = 100;
    strcpy(sdMsg->sipStartLine.reasonPhrase, "Trying");
    sdMsg->sipEntity.sipHdrContentLength = 0;
    sdMsg->sipGenHdrFlag[0] = SIP_HDR_CALL_ID_MASK | SIP_HDR_CSEQ_MASK |
                              SIP_HDR_FROM_MASK | SIP_HDR_TO_MASK | SIP_HDR_VIA_MASK;
    sdMsg->sipReStruct.sipReHdrFlag[0] = 0;
    sip_transport_send_msg(&sipSendMsg);
    
    return 0;
}

int sip_send_504(SIP_API_STRUCT *ackMsg, SIP_TRANSACTION *trans)
{
    SIP_MSG     *sdMsg = &sipSendMsg.sipApiMsg.sipMsg;

    if ((ackMsg == NULL) || (trans == NULL))
    {
        sprintf((char *)sipAsciTempBuf, "sip_send_504:msg or transaction is NULL\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    memset((BYTE *) &sipSendMsg, 0, sizeof(SIP_API_STRUCT));
    memcpy((BYTE *) &sipSendMsg, (BYTE *) ackMsg, sizeof(SIP_API_STRUCT));
    
    sipSendMsg.sipApiType = SIP_API_RES_MSG;
    sdMsg->sipStartLine.statusCode = 504;
    strcpy(sdMsg->sipStartLine.reasonPhrase, "Server Time-out");
    sdMsg->sipEntity.sipHdrContentLength = 0;
    sdMsg->sipGenHdrFlag[0] = SIP_HDR_CALL_ID_MASK | SIP_HDR_CSEQ_MASK |
                              SIP_HDR_FROM_MASK | SIP_HDR_TO_MASK | SIP_HDR_VIA_MASK;
    sdMsg->sipReStruct.sipReHdrFlag[0] = 0;
    sip_transport_send_msg(&sipSendMsg);
    
    return 0;
}

int sip_send_option_rsp(SIP_API_STRUCT *sipApiMsg)
{
    SIP_MSG     *sdMsg;
    BYTE            num = 0;

    if (sipApiMsg == NULL)
    {
        sprintf((char *)sipAsciTempBuf, "sip_send_option_rsp:sipApiMsg is NULL\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    memset((BYTE *) &sipSendMsg, 0, sizeof(SIP_API_STRUCT));
    
    memcpy((BYTE *) &sipSendMsg, (BYTE *) sipApiMsg, sizeof(SIP_API_STRUCT));

    sdMsg = &sipSendMsg.sipApiMsg.sipMsg;
    sipSendMsg.sipApiType = SIP_API_RES_MSG;
    sdMsg->sipStartLine.statusCode = 200;
    strcpy(sdMsg->sipStartLine.reasonPhrase, "OK");
    sdMsg->sipEntity.sipHdrContentLength = 0;
    sdMsg->sipGenHdrFlag[0] = SIP_HDR_CALL_ID_MASK | SIP_HDR_CSEQ_MASK |
                              SIP_HDR_FROM_MASK | SIP_HDR_TO_MASK | SIP_HDR_VIA_MASK | SIP_HDR_ALLOW_MASK;

    sdMsg->sipHdrAllow.allowMethod[num++] = SIP_METHOD_REGISTER;
    sdMsg->sipHdrAllow.allowMethod[num++] = SIP_METHOD_INVITE;
    sdMsg->sipHdrAllow.allowMethod[num++] = SIP_METHOD_ACK;
    sdMsg->sipHdrAllow.allowMethod[num++] = SIP_METHOD_CANCEL;
    sdMsg->sipHdrAllow.allowMethod[num++] = SIP_METHOD_BYE;
    sdMsg->sipHdrAllow.allowMethod[num++] = SIP_METHOD_OPTIONS;
    sdMsg->sipHdrAllow.allowMethod[num++] = SIP_METHOD_INFO;

    sdMsg->sipHdrAllow.num = num;

    sdMsg->sipReStruct.sipReHdrFlag[0] = 0;

    sip_transport_send_msg(&sipSendMsg);
    
    return 0;
}

int sip_send_call_not_exit_rsp(SIP_API_STRUCT *sipApiMsg)
{
    SIP_MSG     *sdMsg = &sipSendMsg.sipApiMsg.sipMsg;

    if (sipApiMsg == NULL)
    {
        sprintf((char *)sipAsciTempBuf, "sip_send_call_not_exit_rsp:sipApiMsg is NULL\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    memset((BYTE *) &sipSendMsg, 0, sizeof(SIP_API_STRUCT));
    
    memcpy((BYTE *) &sipSendMsg, (BYTE *) sipApiMsg, sizeof(SIP_API_STRUCT));
    
    sipSendMsg.sipApiType = SIP_API_RES_MSG;
    sdMsg->sipStartLine.statusCode = 481;
    strcpy(sdMsg->sipStartLine.reasonPhrase, "Call/Transaction Does Not Exist");
    sdMsg->sipEntity.sipHdrContentLength = 0;
    sdMsg->sipGenHdrFlag[0] = SIP_HDR_CALL_ID_MASK | SIP_HDR_CSEQ_MASK |
                              SIP_HDR_FROM_MASK | SIP_HDR_TO_MASK | SIP_HDR_VIA_MASK;

    sdMsg->sipReStruct.sipReHdrFlag[0] = 0;

    sip_transport_send_msg(&sipSendMsg);
    
    return 0;
}

int sip_send_not_find_rsp(SIP_API_STRUCT *sipApiMsg)
{
    SIP_MSG     *sdMsg = &sipSendMsg.sipApiMsg.sipMsg;

    if (sipApiMsg == NULL)
    {
        sprintf((char *)sipAsciTempBuf, "sip_send_not_find_rsp:sipApiMsg is NULL\r\n");
        sip_log_err(sipAsciTempBuf);
        return -1;
    }

    memset((BYTE *) &sipSendMsg, 0, sizeof(SIP_API_STRUCT));
    
    memcpy((BYTE *) &sipSendMsg, (BYTE *) sipApiMsg, sizeof(SIP_API_STRUCT));
    
    sipSendMsg.sipApiType = SIP_API_RES_MSG;
    sdMsg->sipStartLine.statusCode = 404;
    strcpy(sdMsg->sipStartLine.reasonPhrase, "Not Found");
    sdMsg->sipEntity.sipHdrContentLength = 0;
    sdMsg->sipGenHdrFlag[0] = SIP_HDR_CALL_ID_MASK | SIP_HDR_CSEQ_MASK |
                              SIP_HDR_FROM_MASK | SIP_HDR_TO_MASK | SIP_HDR_VIA_MASK;

    sdMsg->sipReStruct.sipReHdrFlag[0] = 0;

    sip_transport_send_msg(&sipSendMsg);
    
    return 0;
}

/*int sip_send_allow()
{
}*/
