
/*******************************************/
/*Title:  sclc.c                           */
/*Descr:  SCCP Connectionless Control      */
/*Author: Liang Hanxi                      */
/*Create: 2002-2-19                            */

/*******************************************/

#include "./include/sccp.h"

// fix multiple definition====================================
SCCP_SegMsgBuf sccp_segmsgbuf[MAX_SEGMSG_BUF];
//

/*===========export================*/
int scrc2sclc ( Intra_Msg * pIntraMsg );
int sclc_rf ( Intra_Msg * pIntraMsg );

/*===========import================*/
extern int sclc2scmg ( Intra_Msg * intramsg );  //scmg.c
extern int scrc_route ( Intra_Msg * pIntraMsg, BOOL ForceAnsi );        //scrc.c
extern int scrc_mnp_route ( Intra_Msg * pIntraMsg, BOOL ForceAnsi );    //scrc.c
extern int send_msg ( Intra_Msg * pIntraMsg );  //scrc.c
extern void spLogDebug ( DWORD mask, const char *fmt, ... );
extern void spShowBCD(DWORD mask, BYTE *buf, int len);
extern void spShowMsg(DWORD mask, const char *pDesc, Intra_Msg *pIntraMsg);
extern void spLog ( char *info );
extern int GetMSISDNOfSSN(BYTE ssn, BYTE *msisdn);

static SCLC_BUF SCLC_OutBuf;
static SCLC_BUF SCLC_InBuf[MAX_SCLC_BUF];

/* buffer changed from 3 to 4, Pierre , 11-07 */

int RecvXUDTMsg ( Intra_Msg * pIntraMsg, BYTE nbuf );
int CheckSegUnID ( Intra_Msg * pIntraMsg );
int RsmRegMsg ( SCLC_MSG * pmsg, SCCP_SegMsgBuf * pSegMsgbuf, Intra_Msg * pIntraMsg );
extern void spLogSeg ( SCCP_SegMsgBuf * pSegMsgbuf );

int scrc2sclc ( Intra_Msg * pIntraMsg )
{
    SCLC_MSG *pmsg;
    short writesub, readsub;
    BYTE nbuf;

    SccpCsta[SccpCstaInd].utilization[4 - 3]++;
    if( pIntraMsg->msgMNP )
    {
        nbuf = 1;
        sccpmsg_st.mnp_route++;
        if(pIntraMsg->msgsource == FROM_MTP)
        {
                pIntraMsg->SLS = LocalSSN[pIntraMsg->CDA.SSN].local+1;
        }
    }                           /* added by pierre for MNP , 2005-11-07 */
    else
    {
        nbuf = LocalSSN[pIntraMsg->CDA.SSN].nbuf % MAX_SCLC_BUF;
    }

    switch ( pIntraMsg->msgtype )
    {
    case UDT_MSG:
        break;
    case XUDT_MSG:
        switch ( RecvXUDTMsg ( pIntraMsg, nbuf ) )
        {
        case 0:
            break;
        case 1:
            break;
        case 2:
            break;
        case 3:
            break;

        }
        return 0;
    case LUDT_MSG:
        spLogDebug ( SCCPDB_UDT | SCCPDB_ERR, "<005>LUDT/XUDT message is not supported" );
        return 0;
    case UDTS_MSG:
		break;
    case XUDTS_MSG:
    case LUDTS_MSG:
        spLogDebug ( SCCPDB_UDT | SCCPDB_ERR, "<005>LUDTS/XUDTS message is not supported" );
        return 0;
    }
    if( pIntraMsg->CDA.SSN == SSN_SCMG )
        return sclc2scmg ( pIntraMsg );
    else
    {
        writesub = SCLC_InBuf[nbuf].writesub;
        readsub = SCLC_InBuf[nbuf].readsub;
        pmsg = &SCLC_InBuf[nbuf].msglist[writesub];

        pmsg->msglen = pIntraMsg->msglen % SCCP_MSG_MAXLEN;
        memcpy ( pmsg->msg, pIntraMsg->data, pmsg->msglen );
        memcpy ( &( pmsg->src_addr ), &( pIntraMsg->CGA ), sizeof ( SCCP_ADDR ) );
        memcpy ( &( pmsg->dst_addr ), &( pIntraMsg->CDA ), sizeof ( SCCP_ADDR ) );
		pmsg->sls = pIntraMsg->SLS;

        if( ( SCLC_InBuf[nbuf].writesub + 1 ) == SCLC_InBuf[nbuf].readsub )
            spShowMsg ( SCCPDB_UDT, "USER <== SCCP: buf overflow!!!!!!!", pIntraMsg );

        SCLC_InBuf[nbuf].writesub = ( writesub + 1 ) % SS_MSG_NUM;
        if( SCLC_InBuf[nbuf].writesub == readsub )
            SCLC_InBuf[nbuf].readsub = ( readsub + 1 ) % SS_MSG_NUM;
		
		if (pIntraMsg->msgtype == UDTS_MSG)
		{
			pmsg->primitive = N_NOTICE_IND;
			spShowMsg ( SCCPDB_UDT, "USER <== SCCP: N-NOTICE", pIntraMsg );
		}
		else
		{
			pmsg->primitive = N_UNITDATA_IND;
			spShowMsg ( SCCPDB_UDT, "USER <== SCCP: UDT Message", pIntraMsg );
		}		
    }
    return 1;
}

int sclc_rf ( Intra_Msg * pIntraMsg )
{
    SCCP_ADDR swapaddr;

    spShowMsg ( SCCPDB_UDT | SCCPDB_ERR, "<006>Route Failure", pIntraMsg );
    switch ( pIntraMsg->msgtype )
    {
    case UDT_MSG:
        if( pIntraMsg->msgsource == FROM_MTP || pIntraMsg->msgsource == FROM_SCLC )
        {
            memcpy ( &swapaddr, &( pIntraMsg->CDA ), sizeof ( SCCP_ADDR ) );
            memcpy ( &( pIntraMsg->CDA ), &( pIntraMsg->CGA ), sizeof ( SCCP_ADDR ) );
            memcpy ( &( pIntraMsg->CGA ), &swapaddr, sizeof ( SCCP_ADDR ) );
            pIntraMsg->CDA.ip = 0xFFFFFFFF;
            if( pIntraMsg->CDA.RI == RI_SSN )
            {
                if( pIntraMsg->CDA.DPC == 0 )
                    pIntraMsg->CDA.DPC = pIntraMsg->CGA.DPC;
            }
            pIntraMsg->msgsource = FROM_SCLC;
            pIntraMsg->msgtype = UDTS_MSG;
            return scrc_route ( pIntraMsg, 0 );
        }
        break;
    case XUDT_MSG:
    case LUDT_MSG:
        //unsupported now       
        break;
    case UDTS_MSG:
        break;
    case XUDTS_MSG:
    case LUDTS_MSG:
        //unsupported now                       
        break;
    }
    return -1;
}

int scmg2sclc ( Intra_Msg * pIntraMsg )
{
    return scrc_route ( pIntraMsg, 0 );
}

/******************************************************************/

/*==================	User Interface----->		================*/

/******************************************************************/
int sclc_send ( SCLC_MSG * pmsg )
{
    if( pmsg->msglen > 256 )
    {
        spLogDebug ( SCCPDB_ERR | SCCPDB_UDT, "<007>User ==> SCCP: Message's Length exceed 256" );
        spShowBCD ( SCCPDB_ERR, pmsg->msg, pmsg->msglen % 256 );
        return 0;
    }
    SccpCsta[SccpCstaInd].utilization[0]++;

    memcpy ( &SCLC_OutBuf.msglist[SCLC_OutBuf.writesub], pmsg, sizeof ( SCLC_MSG ) );
    SCLC_OutBuf.writesub = ( SCLC_OutBuf.writesub + 1 ) % SS_MSG_NUM;
    if( SCLC_OutBuf.writesub == SCLC_OutBuf.readsub )
    {
        spLogDebug ( SCCPDB_ERR | SCCPDB_UDT, "<008>SCLC Out Buffer Overflow" );
        SCLC_OutBuf.readsub = ( SCLC_OutBuf.readsub + 1 ) % SS_MSG_NUM;
    }

    return 1;
}

int sclc_receive ( SCLC_MSG * pmsg, BYTE usertype )
{
    short readsub;

    usertype %= MAX_SCLC_BUF;   /* revised by pierre */
    readsub = SCLC_InBuf[usertype].readsub % SS_MSG_NUM;
    if( SCLC_InBuf[usertype].writesub == readsub )
        return 0;

    memcpy ( pmsg, &SCLC_InBuf[usertype].msglist[readsub], sizeof ( SCLC_MSG ) );
    SCLC_InBuf[usertype].readsub = ( readsub + 1 ) % SS_MSG_NUM;

    return 1;
}

int need_mnp(u8 mnp_type, u8 src_ssn, u8 dst_ssn, u8 *src_digits, u8 digits_len, u8 msg_begin)
{
	u8 msc_digit[10];	

	switch(mnp_type)
	{
		case 0:
			return 0;
			break;
		case 1://Ansi IN
			if(dst_ssn==6 && (src_ssn ==8 || src_ssn==147 ||src_ssn==11) && msg_begin==0x62)
			{
				GetMSISDNOfSSN(8, msc_digit);
				
				if(src_ssn ==8 && !memcmp(msc_digit, src_digits, (digits_len+1)/2))//msc sri
					return 0;
				else 
					return 1;//smsc pps sri
			}
			break;
		case 2://SRF
			if(dst_ssn==6 && (src_ssn ==8 || src_ssn==147 ||src_ssn==11) && msg_begin==0x62)
				return 1;
			break;
		default :
			break;
			
	}
		return 0;
}
void sclc_timer (  )
{
    Intra_Msg outmsg;
    SCLC_MSG *pmsg;
    int loop = 128;
    short readsub;
	u8 msc_digit[10];	

    int SegMsgIndex;
    outmsg.OPC = 0;
    for ( SegMsgIndex = 0; SegMsgIndex < MAX_SEGMSG_BUF; SegMsgIndex++ )
    {
        if( sccp_segmsgbuf[SegMsgIndex].SegMsgTimer && sccp_segmsgbuf[SegMsgIndex].SegMsgTimer++ > MAX_SEGMSG_TIMER )
        {
            spLogDebug ( SCCPDB_ERR, "SCCP XUDT Msg Timer Out. " );
            spLogSeg ( &sccp_segmsgbuf[SegMsgIndex] );
            memset ( &sccp_segmsgbuf[SegMsgIndex], 0, sizeof ( SCCP_SegMsgBuf ) );
        }
    }

    while ( loop-- > 0 )
    {
        if( SCLC_OutBuf.readsub == SCLC_OutBuf.writesub )
            return;

        readsub = SCLC_OutBuf.readsub % SS_MSG_NUM;
        pmsg = &SCLC_OutBuf.msglist[readsub];
        SCLC_OutBuf.readsub = ( readsub + 1 ) % SS_MSG_NUM;

        outmsg.msgsource = FROM_SCLC;
        outmsg.msgtype = UDT_MSG;
        outmsg.msgclass = 0;
        outmsg.SLS = pmsg->sls;
		outmsg.sequenceFlag = pmsg->sequence_control;

        memcpy ( &( outmsg.CDA ), &pmsg->dst_addr, sizeof ( SCCP_ADDR ) );
        memcpy ( &( outmsg.CGA ), &pmsg->src_addr, sizeof ( SCCP_ADDR ) );

        outmsg.NetID = outmsg.CGA.NetID = outmsg.CDA.NetID;
        //              outmsg.CDA.TT = 0;
        outmsg.CDA.ip = 0xFFFFFFFF;
        outmsg.msglen = pmsg->msglen % 256;
        memcpy ( outmsg.data, pmsg->msg, pmsg->msglen % 256 );

//        if( MNP_Flag[0] != 0 && outmsg.CDA.NP == 1 && outmsg.CDA.SSN == 6 && pmsg->msg[0] == 0x62 )
	if(need_mnp(MNP_Flag[0], outmsg.CGA.SSN, outmsg.CDA.SSN, outmsg.CGA.GTAI, outmsg.CGA.len, pmsg->msg[0]))
        {
            /* MNP supported */
            if( MNP_Flag[1] != 2 )      /* Direct routing */
            {
		GetMSISDNOfSSN(8, msc_digit);
		if( MNP_Flag[0] == 1 && outmsg.CDA.TT != 0 &&  outmsg.CGA.SSN != 10)
                {
                    /* IN_based call related message */
					spLogDebug ( SCCPDB_UDT, "User ==> SCCP ==> MNP_SRF: IN_based MNP and Call_related message, routed to MNP" );
                    //spShowMsg(SCCPDB_USER, "User ==> SCCP: UDT Message", &outmsg);
                    //scrc_route(&outmsg);
                    outmsg.msgMNP = 1;
                    scrc2sclc ( &outmsg );
		    continue;
                }
                else if( outmsg.CGA.SSN != 10 )//&& (!(!memcmp(msc_digit, outmsg.CGA.GTAI, (outmsg.CGA.GTAI+1)/2) && MNP_Flag[0] == 1 ) ))
                {
                    spShowMsg ( SCCPDB_USER, "User ==> SCCP ==> MNP_SRF : UDT Message", &outmsg );

					outmsg.msgMNP = 1;
                    scrc2sclc ( &outmsg );
                    continue;
                }
            }
        }

        spShowMsg ( SCCPDB_USER, "User ==> SCCP: UDT Message", &outmsg );
        scrc_route ( &outmsg, 0 );
    }
    return;
}

/* added by Pierre for MNP, 2005-11-07 */
int sclc_mnp_send ( SCLC_MSG * pmsg )
{
    Intra_Msg outmsg;

    if( pmsg->msglen > 256 )
    {
        spLogDebug ( SCCPDB_ERR | SCCPDB_UDT, "<007>User ==> SCCP: Message's Length exceed 256" );
        spShowBCD ( SCCPDB_ERR, pmsg->msg, pmsg->msglen % 256 );
        return 0;
    }
    SccpCsta[SccpCstaInd].utilization[0]++;

    sccpmsg_st.mnp_send++;
    outmsg.msgsource = FROM_SCLC;
    outmsg.msgtype = UDT_MSG;
    outmsg.msgclass = 0;
    outmsg.SLS = pmsg->sls;

    memcpy ( &( outmsg.CDA ), &pmsg->dst_addr, sizeof ( SCCP_ADDR ) );
    memcpy ( &( outmsg.CGA ), &pmsg->src_addr, sizeof ( SCCP_ADDR ) );

    outmsg.NetID = outmsg.CGA.NetID = outmsg.CDA.NetID;
    //outmsg.CDA.TT = 0;
    outmsg.CDA.ip = 0xFFFFFFFF;
    outmsg.msglen = pmsg->msglen % 256;
    memcpy ( outmsg.data, pmsg->msg, pmsg->msglen % 256 );

    spShowMsg ( SCCPDB_USER, "User ==> SCCP: UDT Message", &outmsg );

    return scrc_mnp_route ( &outmsg, 0 );

}

//add for UDT SegmentingMsg to XUDT --lw 2007/03/20
int SegmentingMsg ( Intra_Msg * pIntraMsg )
{
    Intra_Msg pIntraMsgSeg1, pIntraMsgSeg2;
    int ret1, ret2;
    BYTE sSegLR[4];

    ret1 = ret2 = 0;

    memcpy ( &pIntraMsgSeg1, pIntraMsg, sizeof ( Intra_Msg ) );
    memcpy ( &pIntraMsgSeg2, pIntraMsg, sizeof ( Intra_Msg ) );

    pIntraMsgSeg1.msglen = pIntraMsg->msglen / 2;
    pIntraMsgSeg2.msglen = pIntraMsg->msglen - pIntraMsgSeg1.msglen;

    memset ( &pIntraMsgSeg1.data[pIntraMsgSeg1.msglen], 0, SCCP_MSG_MAXLEN - pIntraMsgSeg1.msglen );
    memcpy ( &pIntraMsgSeg2.data[0], &pIntraMsg->data[pIntraMsgSeg1.msglen], pIntraMsgSeg2.msglen );
    memset ( &pIntraMsgSeg2.data[pIntraMsgSeg2.msglen], 0, SCCP_MSG_MAXLEN - pIntraMsgSeg2.msglen );

    pIntraMsgSeg1.msgtype = pIntraMsgSeg2.msgtype = XUDT_MSG;
    pIntraMsgSeg1.SegPresent = pIntraMsgSeg2.SegPresent = 1;
    pIntraMsgSeg1.Segmnt.CBit = pIntraMsgSeg2.Segmnt.CBit = 1;  //sequence
    pIntraMsgSeg1.Segmnt.FBit = 1;
    pIntraMsgSeg2.Segmnt.FBit = 0;
    pIntraMsgSeg1.Segmnt.RSBits = 1;
    pIntraMsgSeg2.Segmnt.RSBits = 0;
    pIntraMsgSeg1.Hop = pIntraMsgSeg1.Hop = 0;
    sSegLR[0] = ( SCCP_Param.ip >> 16 ) & 0x0001;       //plant number
    sSegLR[1] = pIntraMsg->SLS;
    sSegLR[2] = SCCPCapBuf.watch_dog[128]++;
    memcpy ( pIntraMsgSeg1.Segmnt.SegLR, sSegLR, SEG_RS_LEN );
    memcpy ( pIntraMsgSeg2.Segmnt.SegLR, sSegLR, SEG_RS_LEN );

    spLogDebug ( SCCPDB_UDT, "SCCP =>SCCP_RegProc=> SCCP : Length [%d Bytes] [%d Bytes]\r\n", pIntraMsgSeg1.msglen, pIntraMsgSeg2.msglen );

    ret1 = send_msg ( &pIntraMsgSeg1 );

    ret2 = send_msg ( &pIntraMsgSeg2 );

    return ( ret1 > 0 && ret2 > 0 );
}

int RecvXUDTMsg ( Intra_Msg * pIntraMsg, BYTE nbuf )
{
    SCLC_MSG *pmsg;
    short writesub, readsub;
    int SegMsgIndex;

    if( !pIntraMsg->SegPresent )        //Not Include Segmentation Paramenters  
    {
        return -1;
    }

    if( pIntraMsg->Segmnt.FBit == 1 && pIntraMsg->Segmnt.RSBits == 0 )  //Single Segmetaion
    {
        return -1;
    }

    SegMsgIndex = CheckSegUnID ( pIntraMsg );

    if( SegMsgIndex == MAX_SEGMSG_BUF + 1 )     //check CGA SLR MTP3 routing lable is idle
    {
        return 0;
    }

    else if( SegMsgIndex == MAX_SEGMSG_BUF )    //first Segmentation
    {
        if( pIntraMsg->Segmnt.FBit != 1 )
        {
            spLogDebug ( SCCPDB_ERR, "SCCP Recv new XUDT Msg but the Fbit is not 1." );
            return 0;
        }

        for ( SegMsgIndex = 0; SegMsgIndex < MAX_SEGMSG_BUF; SegMsgIndex++ )
        {
            if( sccp_segmsgbuf[SegMsgIndex].MsgState == SEGSTREAM_IDLE )
            {
                int SegBlockIndex;
                SCCP_SegStream *pSegStream;
                SCCP_SegMsgBuf *pSegMsgbuf = &sccp_segmsgbuf[SegMsgIndex];

                pSegMsgbuf->MsgClass = pIntraMsg->Segmnt.CBit;
                pSegMsgbuf->MsgTotal = pIntraMsg->Segmnt.RSBits + 1;
                pSegMsgbuf->RSE = pIntraMsg->Segmnt.RSBits - 1;

                pSegMsgbuf->SegID.DPC = pIntraMsg->DPC;
                pSegMsgbuf->SegID.OPC = pIntraMsg->OPC;
                pSegMsgbuf->SegID.SLS = pIntraMsg->SLS;
                memcpy ( &pSegMsgbuf->SegID.CGA, &pIntraMsg->CGA, sizeof ( SCCP_ADDR ) );
                memcpy ( &pSegMsgbuf->SegID.SegLR, &pIntraMsg->Segmnt.SegLR, SEG_RS_LEN );

                SegBlockIndex = pSegMsgbuf->MsgTotal - ( pIntraMsg->Segmnt.RSBits + 1 );
                pSegStream = &pSegMsgbuf->SegStream[SegBlockIndex];
                pSegStream->SegDataLen = pIntraMsg->msglen;
                memcpy ( &pSegStream->SegDataBlock, &pIntraMsg->data, pIntraMsg->msglen );

                pSegMsgbuf->SegMsgTimer = 1;
                pSegMsgbuf->MsgState = SEGSTREAM_BUSY;

                return 1;
            }
        }

        if( SegMsgIndex == MAX_SEGMSG_BUF )
        {
            spLogDebug ( SCCPDB_ERR, "SCCP Recv new XUDT but SCCP SegMsg buf is not enough" );
            return 0;
        }
    }
    else                        //not first Segmentation
    {
        int SegBlockIndex;
        int i, j, linemax;
        char info[2560 * 3 + 512], temp_str[128];
        SCCP_SegStream *pSegStream;
        SCCP_SegMsgBuf *pSegMsgbuf = &sccp_segmsgbuf[SegMsgIndex];

        if( pIntraMsg->Segmnt.RSBits != pSegMsgbuf->RSE )
        {
            spLogDebug ( SCCPDB_ERR, "SCCP Recv unexpect RS XUDT Msg , discard it" );
            return 0;
        }

        if( pIntraMsg->Segmnt.FBit == 1 )
        {
            spLogDebug ( SCCPDB_ERR, "SCCP Recv XUDT Msg dupulicate first segment. discard it" );
            return 0;
        }

        SegBlockIndex = pSegMsgbuf->MsgTotal - ( pIntraMsg->Segmnt.RSBits + 1 );
        pSegStream = &pSegMsgbuf->SegStream[SegBlockIndex];

        if( pSegStream->SegDataLen )
        {
            spLogDebug ( SCCPDB_ERR, "SCCP Recv XUDT Msg dupulicate segment, discard it[RS :%d]", pIntraMsg->Segmnt.RSBits );
            return 0;
        }
        pSegStream->SegDataLen = pIntraMsg->msglen;
        memcpy ( &pSegStream->SegDataBlock, &pIntraMsg->data, pIntraMsg->msglen );

        if( pSegMsgbuf->RSE )
        {
            pSegMsgbuf->RSE--;
            return 1;
        }

        //last segment
        pSegMsgbuf->SegMsgTimer = 0;
        writesub = SCLC_InBuf[nbuf].writesub;
        readsub = SCLC_InBuf[nbuf].readsub;
        pmsg = &SCLC_InBuf[nbuf].msglist[writesub];

        if( !RsmRegMsg ( pmsg, pSegMsgbuf, pIntraMsg ) )
        {
            return 0;
        }

        if( ( SCLC_InBuf[nbuf].writesub + 1 ) == SCLC_InBuf[nbuf].readsub )
            spShowMsg ( SCCPDB_UDT, "USER <== SCCP: buf overflow!!!!!!!", pIntraMsg );

        SCLC_InBuf[nbuf].writesub = ( writesub + 1 ) % SS_MSG_NUM;
        if( SCLC_InBuf[nbuf].writesub == readsub )
            SCLC_InBuf[nbuf].readsub = ( readsub + 1 ) % SS_MSG_NUM;

        spLogDebug ( SCCPDB_UDT,  "\r\n\r\nUser <== SCCP_RegProc. XUDT Message" );
        spLogSeg ( pSegMsgbuf );
        info[0] = '\0';
        sprintf ( temp_str, "Segmentaion Length info: \r\n" );
        strcat ( info, temp_str );
        for ( i = 0; i < pSegMsgbuf->MsgTotal; i++ )
        {
            sprintf ( temp_str, "[%02d]:%d ", i, pSegMsgbuf->SegStream[i].SegDataLen );
            strcat ( info, temp_str );
            if( i == 7 )
            {
                strcat ( info, "\r\n" );
            }
        }
        spLogDebug ( SCCPDB_UDT, info );

        memset ( info, 0, 2560 * 3 + 512 );
        i = j = linemax = 0;
        while ( i * 16 < pmsg->msglen )
        {
            if( ( linemax = pmsg->msglen - 16 * i ) > 16 )
                linemax = 16;
            for ( j = 0; j < linemax; j++ )
            {
                sprintf ( info + 3 * j + ( j > 7 ? 1 : 0 ), "%02X ", pmsg->msg[16 * i + j] );
                if( j == 7 )
                {
                    sprintf ( info + 3 * 8, " " );
                }
            }
            spLogDebug ( SCCPDB_UDT,info );
            i++;
        }

        memset ( pSegMsgbuf, 0, sizeof ( SCCP_SegMsgBuf ) );
        return 1;
    }

    return 0;
}

int CheckSegUnID ( Intra_Msg * pIntraMsg )
{
    int SegMsgIndex, nCheckFlag;
    SCCP_SegUnID *pSegId;

    nCheckFlag = 0;
    for ( SegMsgIndex = 0; SegMsgIndex < MAX_SEGMSG_BUF; SegMsgIndex++ )
    {
        pSegId = &sccp_segmsgbuf[SegMsgIndex].SegID;
        if( memcmp ( &pSegId->SegLR, &pIntraMsg->Segmnt.SegLR, SEG_RS_LEN ) )
        {
            continue;
        }

        if( pSegId->DPC != pIntraMsg->DPC )     //have routed , equal of course 
        {
            spLogDebug ( SCCPDB_ERR, "SCCP XUDT Msg check MTP3 routing lable fail , DPC is not matched!" );
            nCheckFlag = 1;;
        }
        if( pSegId->OPC != pIntraMsg->OPC )
        {
            spLogDebug ( SCCPDB_ERR, "SCCP XUDT Msg check MTP3 routing lable fail , OPC is not matched!" );
            nCheckFlag = 1;
        }
        if( pSegId->SLS != pIntraMsg->SLS )
        {
            spLogDebug ( SCCPDB_ERR, "SCCP XUDT Msg check MTP3 routing lable fail , SLS is not matched!" );
            nCheckFlag = 1;
        }
        if( memcmp ( &pSegId->CGA, &pIntraMsg->CGA, sizeof ( SCCP_ADDR ) ) )
        {
            spLogDebug ( SCCPDB_ERR, "SCCP XUDT Msg check MTP3 routing lable fail , CGA is not matched!" );
            nCheckFlag = 1;
        }

        if( nCheckFlag )        //act as a new segmention start
        {
            if( pIntraMsg->Segmnt.FBit == 1 && pIntraMsg->Segmnt.RSBits != 0 )
            {
                return MAX_SEGMSG_BUF;
            }
            return MAX_SEGMSG_BUF + 1;
        }

        return SegMsgIndex;
    }
    return SegMsgIndex;
}

int RsmRegMsg ( SCLC_MSG * pmsg, SCCP_SegMsgBuf * pSegMsgbuf, Intra_Msg * pIntraMsg )
{
    int SegBlockIndex, XUDTMsgLen;
    SCCP_SegStream *pSegStream;

    XUDTMsgLen = 0;
    for ( SegBlockIndex = 0; SegBlockIndex < pSegMsgbuf->MsgTotal; SegBlockIndex++ )
    {
        pSegStream = &pSegMsgbuf->SegStream[SegBlockIndex];
        XUDTMsgLen += pSegStream->SegDataLen;
    }

    if( XUDTMsgLen > MAX_SCLCMSG_LEN )
    {
        spLogDebug ( SCCPDB_ERR, "SCCP Reassemble XUDT Msg is too long ,discard it" );
        return 0;
    }

    XUDTMsgLen = 0;
    for ( SegBlockIndex = 0; SegBlockIndex < pSegMsgbuf->MsgTotal; SegBlockIndex++ )
    {
        pSegStream = &pSegMsgbuf->SegStream[SegBlockIndex];
        if((XUDTMsgLen+ pSegStream->SegDataLen)>MAX_SCLCMSG_LEN)
            break;
        memcpy ( pmsg->msg + XUDTMsgLen, pSegStream->SegDataBlock, pSegStream->SegDataLen );
        XUDTMsgLen += pSegStream->SegDataLen;
    }
    pmsg->msglen = XUDTMsgLen;
    memcpy ( &( pmsg->src_addr ), &( pIntraMsg->CGA ), sizeof ( SCCP_ADDR ) );
    memcpy ( &( pmsg->dst_addr ), &( pIntraMsg->CDA ), sizeof ( SCCP_ADDR ) );

    return 1;
}

