//附着接受, 更新MAP中原有用户的TLLI(可选), 并记录事件
void CGprsSynthesize::AttachAccept(SPcapSignal& signal)
{
    ++ CStatistics::count_attach_accept;

    //network----->MS
    CKey key(signal.currai, signal.curtlli);

    CUserInfo* pUserInfo = m_InfoDB.FindUserInfo(key);
    if(!pUserInfo)
    {
        printf("GPRS attach accept, can't find user userinfo: rai[%lld] tlli[%d]\n", signal.currai.value, signal.curtlli);
        return;
    }

    //pUserInfo->TDR.SetEndTime();
	pUserInfo->TDR.SetEndTime(getTime(signal.pdu));
    pUserInfo->TDR.SetImsi(getImsi(signal.pdu));
    pUserInfo->TDR.SetType(GPRS_ATTACH_EVENT);
    pUserInfo->TDR.SetResult(true);
    pUserInfo->TDR.SetCause(getGmmCause(signal.pdu));
    //pUserInfo->TDR.Output();
	sysPtr->writeGPRSTDR(&pUserInfo->TDR.m_Tdr);

    pUserInfo->CDR.SetImsi(getImsi(signal.pdu));
    pUserInfo->CDR.SetDlci(getDlci(signal.pdu));
    pUserInfo->CDR.SetBvci(getBvci(signal.pdu));
    pUserInfo->CDR.SetTlli(getCurTlli(signal.pdu));
    pUserInfo->CDR.SetOriCgi(getCgi(signal.pdu));
    return;
}
//路由区更新接受, 更新相应用户数据,并记录事件
void CGprsSynthesize::RoutingAreaUpdateAccept(SPcapSignal& signal)
{
    //network----->MS
    CKey key(signal.currai, signal.curtlli);

    CUserInfo* pUserInfo = m_InfoDB.FindUserInfo(key);
    if(!pUserInfo)
    {
        printf("GPRS ra update accept, can't find UserInfo: rai[%lld] tlli[%d]\n", signal.currai.value, signal.curtlli);
        return;
    }
    else
    {
        //printf("Routing Aera Update Accept BVCI = %d, TLLI = 0x%04x\n", ntohs(bvci), ntohl(tlli));
    }

    //pUserInfo->TDR.SetEndTime();
	pUserInfo->TDR.SetEndTime(getTime(signal.pdu));
    pUserInfo->TDR.SetResult(true);
    pUserInfo->TDR.SetCause(getGmmCause(signal.pdu));
    if(pUserInfo->TDR.m_Tdr.m_Imsi[0] == '\0') pUserInfo->TDR.SetImsi(getImsi(signal.pdu));//@090727 ?
    //pUserInfo->TDR.Output();
	sysPtr->writeGPRSTDR(&pUserInfo->TDR.m_Tdr);

    return;
}
void CGprsSynthesize::ModifyPDPcontextRequest(SPcapSignal& signal)
{
    CKey key(signal.currai, signal.curtlli);


    CUserInfo* pUserInfo = m_InfoDB.FindUserInfo(key);
    if(!pUserInfo)
    {
        printf("GPRS modify pdp req, can't find UserInfo: ri[%lld] tlli[%d]\n", signal.currai.value, signal.curtlli);
        return;
    }

    //pUserInfo->TDR.SetBeginTime();
	pUserInfo->TDR.SetBeginTime(getTime(signal.pdu));
    pUserInfo->TDR.SetImsi(getImsi(signal.pdu));
    pUserInfo->TDR.SetType(GPRS_PDP_MODIFY_EVENT);
    pUserInfo->TDR.SetDlci(getDlci(signal.pdu));
    pUserInfo->TDR.SetBvci(getBvci(signal.pdu));
    pUserInfo->TDR.SetTlli(getCurTlli(signal.pdu));
    pUserInfo->TDR.SetCgi(getCgi(signal.pdu));

    pUserInfo->CDR.SetRequestQos(getRequestQos(signal.pdu));

    return;
}
void CGprsSynthesize::DeatachRequest(SPcapSignal& signal)
{
    //@zh add for debug
    TLLI_TYPE tllitp = getTLLIType(signal.curtlli);
    if(tllitp != TLLI_LOCAL)
    {
        //FOR DEBUG
        printf("WARN: GPRS Detach Request using NOT local TLLI!\n");
    }
    //@zh add for debug
    //MS----->network
    //network----->MS
    CKey key(signal.currai, signal.curtlli);

    CUserInfo* pUserInfo = m_InfoDB.FindUserInfo(key);
    if(!pUserInfo)
    {
        printf("GPRS detach request, can't find UserInfo: rai[%lld] tlli[%d], add new user!\n", signal.currai.value, signal.curtlli);
        //@zh add new user
        pUserInfo = m_InfoDB.CreateUserInfo(key);

        //return;
    }

    if(pUserInfo)
    {
        //pUserInfo->TDR.SetBeginTime();
        pUserInfo->TDR.SetBeginTime(getTime(signal.pdu));
        pUserInfo->TDR.SetImsi(getImsi(signal.pdu));
        pUserInfo->TDR.SetType(GPRS_DEATACH_EVENT);
        pUserInfo->TDR.SetDlci(getDlci(signal.pdu));
        pUserInfo->TDR.SetBvci(getBvci(signal.pdu));
        pUserInfo->TDR.SetTlli(getCurTlli(signal.pdu));
        pUserInfo->TDR.SetCgi(getCgi(signal.pdu));

        unsigned char gmmtp = getGMMType(signal.pdu);
        unsigned char dir = DL_UNITDATA;
        const UINT8 *pTp = getBssgpPduType(signal.pdu);
        if(pTp) dir = *pTp;
        if(dir == DL_UNITDATA) //network => ms
        {
            if(gmmtp == 3) gmmtp =1; //IMSI detach
            else gmmtp = 0;          //GPRS detach
        }
        else if(dir == UL_UNITDATA) //ms => network
        {
            if(gmmtp == 1) gmmtp = 0;// GPRS detach
            else if(gmmtp == 2) gmmtp = 1;//IMSI detach
            else gmmtp = 2;//Combined GPRS/IMSI detach
            pUserInfo->TDR.SetGMMType(gmmtp);
        }

    }
    return;
}
void CGprsSynthesize::ActivatePDPcontextRequest(SPcapSignal& signal)
{
    CKey key(signal.currai, signal.curtlli);


    CUserInfo* pUserInfo = m_InfoDB.FindUserInfo(key);
    if(!pUserInfo)
    {
        printf("GPRS activate pdp request, can't find UserInfo: ri[%lld] tlli[%d], add new userinfo!\n", signal.currai.value, signal.curtlli);
        pUserInfo = m_InfoDB.CreateUserInfo(key);
        //return;
    }

    if(pUserInfo)
    {
        //pUserInfo->TDR.SetBeginTime();
    	pUserInfo->TDR.SetBeginTime(getTime(signal.pdu));
        pUserInfo->TDR.SetImsi(getImsi(signal.pdu));
        pUserInfo->TDR.SetType(GPRS_AA_PDP_ACTIVATE);
        pUserInfo->TDR.SetDlci(getDlci(signal.pdu));
        pUserInfo->TDR.SetBvci(getBvci(signal.pdu));
        pUserInfo->TDR.SetTlli(getCurTlli(signal.pdu));
        pUserInfo->TDR.SetCgi(getCgi(signal.pdu));

        //pUserInfo->CDR.SetBeginTime();
	    pUserInfo->CDR.SetBeginTime(getTime(signal.pdu));
        pUserInfo->CDR.SetImsi(getImsi(signal.pdu));
        pUserInfo->CDR.SetRequestQos(getRequestQos(signal.pdu));
        pUserInfo->CDR.SetApn(getApn(signal.pdu));
        pUserInfo->CDR.SetDlci(getDlci(signal.pdu));
        pUserInfo->CDR.SetBvci(getBvci(signal.pdu));
        pUserInfo->CDR.SetTlli(getCurTlli(signal.pdu));
        pUserInfo->CDR.SetOriCgi(getCgi(signal.pdu));

        return;
    }
}
//路由区更新接受, 更新相应用户数据,并记录事件
void CGprsSynthesize::RoutingAreaUpdateReject(SPcapSignal& signal)
{
    //network----->MS
    CKey key(signal.currai, signal.curtlli);


    CUserInfo* pUserInfo = m_InfoDB.FindUserInfo(key);
    if(!pUserInfo)
    {
        printf("GPRS ra update reject, can't find UserInfo: ri[%lld] tlli[%d]\n", signal.currai.value, signal.curtlli);
        return;
    }

    //pUserInfo->TDR.SetEndTime();
	pUserInfo->TDR.SetEndTime(getTime(signal.pdu));
    pUserInfo->TDR.SetType(GPRS_RA_UPDATE_EVENT);
    pUserInfo->TDR.SetResult(false);
    pUserInfo->TDR.SetCause(getGmmCause(signal.pdu));
    if(pUserInfo->TDR.m_Tdr.m_Imsi[0] == '\0') pUserInfo->TDR.SetImsi(getImsi(signal.pdu));//@090727 ?
    //pUserInfo->TDR.Output();
	sysPtr->writeGPRSTDR(&pUserInfo->TDR.m_Tdr);
    return;
}
//路由区更新请求, 更新相应用户数据
void CGprsSynthesize::RoutingAreaUpdateRuequest(SPcapSignal& signal)
{
    //MS----->network
    CUserInfo* pUserInfo = NULL;
    CKey cur(signal.currai, signal.curtlli);
    TLLI_TYPE tllitp = getTLLIType(signal.curtlli);
    if(tllitp == TLLI_FOREIGN)
    {
        unsigned int localtlli = signal.curtlli | 0x40000000;
        CKey old(signal.oldrai, localtlli);
        pUserInfo = m_InfoDB.ChangeKey(old, cur);
    }
    else if(tllitp == TLLI_LOCAL)
    {
    }
    else if(tllitp == TLLI_RANDOM)
    {
        //for test
        printf("WARN: RoutingAreaUpdate Request using RANDOM TLLI!\n");
    }

    if(!pUserInfo)
        pUserInfo = m_InfoDB.FindUserInfo(cur);
    if(!pUserInfo)
    {
        //@zh add new user
        printf("GPRS ra update request, can not find userinfo: rai[%lld] tlli[%d], add new userinfo!\n", signal.currai.value, signal.curtlli);
        pUserInfo = m_InfoDB.CreateUserInfo(cur);
        //return;
    }

    if(pUserInfo)
    {
        //pUserInfo->TDR.SetBeginTime();
	    pUserInfo->TDR.SetBeginTime(getTime(signal.pdu));
        pUserInfo->TDR.SetImsi(getImsi(signal.pdu));
        pUserInfo->TDR.SetType(GPRS_RA_UPDATE_EVENT);
        pUserInfo->TDR.SetDlci(getDlci(signal.pdu));
        pUserInfo->TDR.SetBvci(getBvci(signal.pdu));
        pUserInfo->TDR.SetTlli(getCurTlli(signal.pdu));
        pUserInfo->TDR.SetCgi(getCgi(signal.pdu));

        unsigned char gmmtp = getGMMType(signal.pdu);
        if(gmmtp > 3) gmmtp = 3;
        pUserInfo->TDR.SetGMMType(gmmtp);

        pUserInfo->CDR.SetImsi(getImsi(signal.pdu));
        pUserInfo->CDR.SetDlci(getDlci(signal.pdu));
        pUserInfo->CDR.SetBvci(getBvci(signal.pdu));
        pUserInfo->CDR.SetTlli(getCurTlli(signal.pdu));
        pUserInfo->CDR.SetOriCgi(getCgi(signal.pdu));

        return;
    }

    /*//@zh comment
    CKey cur(signal.currai, signal.curtlli);
    CKey old(signal.oldrai, signal.curtlli);


    CUserInfo* pUserInfo = m_InfoDB.ChangeKey(old, cur);
    if(!pUserInfo)
        pUserInfo = m_InfoDB.FindUserInfo(cur);
    if(!pUserInfo)
        return;

    //pUserInfo->TDR.SetBeginTime();
	pUserInfo->TDR.SetBeginTime(getTime(signal.pdu));
    pUserInfo->TDR.SetImsi(getImsi(signal.pdu));
    pUserInfo->TDR.SetType(GPRS_RA_UPDATE_EVENT);
    pUserInfo->TDR.SetDlci(getDlci(signal.pdu));
    pUserInfo->TDR.SetBvci(getBvci(signal.pdu));
    pUserInfo->TDR.SetTlli(getCurTlli(signal.pdu));
    pUserInfo->TDR.SetCgi(getCgi(signal.pdu));

    pUserInfo->CDR.SetImsi(getImsi(signal.pdu));
    pUserInfo->CDR.SetDlci(getDlci(signal.pdu));
    pUserInfo->CDR.SetBvci(getBvci(signal.pdu));
    pUserInfo->CDR.SetTlli(getCurTlli(signal.pdu));
    pUserInfo->CDR.SetOriCgi(getCgi(signal.pdu));

    return;
    *///@zh comment
}
//@zh
void CGprsSynthesize::AttachRequest(SPcapSignal& signal)
{
    ++ CStatistics::count_attach_request;
    //@zh
    CUserInfo* pUserInfo = NULL;
    CKey cur(signal.currai, signal.curtlli);
    TLLI_TYPE tllitp = getTLLIType(signal.curtlli);
    if(tllitp == TLLI_FOREIGN)
    {
        unsigned int localtlli = signal.curtlli | 0x40000000;
        CKey old(signal.oldrai, localtlli);
        pUserInfo = m_InfoDB.ChangeKey(old, cur);
    }
    else if(tllitp == TLLI_LOCAL)
    {
        //FOR DEBUG
        printf("WARN: GPRS Attach Request using local TLLI!\n");
    }
    else if(tllitp == TLLI_RANDOM)
    {}
    if(!pUserInfo)
        pUserInfo = m_InfoDB.FindUserInfo(cur);
    if(!pUserInfo)
        pUserInfo = m_InfoDB.CreateUserInfo(cur);
    //pUserInfo->TDR.SetBeginTime();
	pUserInfo->TDR.SetBeginTime(getTime(signal.pdu));
    pUserInfo->TDR.SetImsi(getImsi(signal.pdu));
    pUserInfo->TDR.SetType(GPRS_ATTACH_EVENT);
    pUserInfo->TDR.SetDlci(getDlci(signal.pdu));
    pUserInfo->TDR.SetBvci(getBvci(signal.pdu));
    pUserInfo->TDR.SetTlli(getCurTlli(signal.pdu));
    pUserInfo->TDR.SetCgi(getCgi(signal.pdu));

    unsigned char gmmtp = getGMMType(signal.pdu);
    if(gmmtp == 2 || gmmtp == 3) gmmtp = 1;
    else gmmtp = 0;
    pUserInfo->TDR.SetGMMType(gmmtp);

    pUserInfo->CDR.SetImsi(getImsi(signal.pdu));
    pUserInfo->CDR.SetDlci(getDlci(signal.pdu));
    pUserInfo->CDR.SetBvci(getBvci(signal.pdu));
    pUserInfo->CDR.SetTlli(getCurTlli(signal.pdu));
    pUserInfo->CDR.SetOriCgi(getCgi(signal.pdu));
    return;
    //@zh

    /* //@zh comment
    //MS----->network
    CKey cur(signal.currai, signal.curtlli);
    CKey old(signal.oldrai, signal.curtlli);

    CUserInfo* pUserInfo = m_InfoDB.ChangeKey(old, cur);
    if(!pUserInfo)
        pUserInfo = m_InfoDB.FindUserInfo(cur);
    if(!pUserInfo)
        pUserInfo = m_InfoDB.CreateUserInfo(cur);

    //pUserInfo->TDR.SetBeginTime();
	pUserInfo->TDR.SetBeginTime(getTime(signal.pdu));
    pUserInfo->TDR.SetImsi(getImsi(signal.pdu));
    pUserInfo->TDR.SetType(GPRS_ATTACH_EVENT);
    pUserInfo->TDR.SetDlci(getDlci(signal.pdu));
    pUserInfo->TDR.SetBvci(getBvci(signal.pdu));
    pUserInfo->TDR.SetTlli(getCurTlli(signal.pdu));
    pUserInfo->TDR.SetCgi(getCgi(signal.pdu));

    pUserInfo->CDR.SetImsi(getImsi(signal.pdu));
    pUserInfo->CDR.SetDlci(getDlci(signal.pdu));
    pUserInfo->CDR.SetBvci(getBvci(signal.pdu));
    pUserInfo->CDR.SetTlli(getCurTlli(signal.pdu));
    pUserInfo->CDR.SetOriCgi(getCgi(signal.pdu));
    return;
    *///@zh comment
}
void CGprsSynthesize::HandleBSSGP(SPcapSignal& signal)
{
    //得到bvci
    const UINT16* bvci = getBvci(signal.pdu);
    if(bvci)
        signal.bvci = *bvci;
    else
    {
        printf("HandleBSSGP no bvci\n");
        return;
    }

    const UINT8* type = getBssgpPduType(signal.pdu);
    if(!type)
    {
        printf("wrong format signal\n");
        return;
    }

    switch(*type)
    {
        default:
            break;

        case 0x00: //CGBPdu::DL_UNITDATA //SGSN to BSS havn't Cell Indentifier
            {
                //根据link和bvci找到所在RAI
                //找到当前TLLI
                //如果有旧的TLLI,则用新的TLLI更新旧的TLLI
                if(!m_RaiMap.FindRai(signal.link, signal.bvci, signal.currai))
                {
                    printf("Handle BSSGP DL_UNITDATA can't find rai in routemap:link[%hd] bvci[%hd] ai[%lld]\n", signal.link, signal.bvci, signal.currai.value);
                    return;
                }

                const UINT32* curtlli = getCurTlli(signal.pdu);
                if(curtlli)
                    signal.curtlli = *curtlli;
                else
                {
                    printf("Handle BSSGP DL_UNITDATA no cur tlli\n");
                    return;
                }

                const UINT32* oldtlli = getOldTlli(signal.pdu);
                if(oldtlli)
                {
                    signal.oldtlli = *oldtlli;

                    CKey cur(signal.currai, signal.curtlli);
                    CKey old(signal.currai, signal.oldtlli);
                    m_InfoDB.ChangeKey(old, cur);
                }
                HandleLLC(signal);
            }
            break;

        case 0x01: //CGBPdu::UL_UNITDATA //BSS to SGSN have Cell Indentifier
            {
                //@zh
                //attatch request/route area update request
                const char* oldrai = getOldRai(signal.pdu);
                if(oldrai)
                {
                   signal.oldrai(oldrai);
                }
                //@zh
                //可以获得CGI  RAI  TLLI(当前)
                const char* rai = getCurRai(signal.pdu);
                if(!rai)
                {
                    printf("Handle BSSGP UL_UNITDATA no rai\n");
                    return;
                }

                signal.currai(rai);

                const UINT32* curtlli = getCurTlli(signal.pdu);
                if(curtlli)
                    signal.curtlli = *curtlli;
                else
                {
                    printf("Handle BSSGP UL_UNITDATA no cur tlli\n");
                    return;
                }

                m_RaiMap.AddRai(signal.link, signal.bvci, signal.currai);
                //@zh for debug
                printf("Hadle BSSGP UL_UNITDATA: add rai -- link[%hd] bvci[%hd] rai[%lld]\n", signal.link, signal.bvci, signal.currai.value);
                HandleLLC(signal);
            }
            break;
            //@zh add
            case 0x59: //PS_HANDOVER_REQUIRED:
            {
                //BSS => SGSN
                const char* rai = getCurRai(signal.pdu);
                if(!rai)
                {
                    printf("HandleBSSGP PS_HANDOVER_REQUIRED no rai\n");
                    return;
                }
                signal.currai(rai);
                //
                const UINT32* curtlli = getCurTlli(signal.pdu);
                if(curtlli)
                    signal.curtlli = *curtlli;
                else
                {
                    printf("HandleBSSGP PS_HANDOVER_REQUIRED no cur tlli\n");
                    return;
                }
                //
                CKey key(signal.currai, signal.curtlli);

                CUserInfo* pUserInfo = m_InfoDB.FindUserInfo(key);
                if(!pUserInfo)
                {
                    //printf("can't find PS_HANDOVER_REQUIRED BVCI = %d, TLLI = 0x%04x\n", ntohs(bvci), ntohl(tlli));
                    return;
                }

                //

                pUserInfo->TDR.SetBeginTime(getTime(signal.pdu));
                pUserInfo->TDR.SetImsi(getImsi(signal.pdu));
                pUserInfo->TDR.SetType(GPRS_HANDOVER_EVENT);
                pUserInfo->TDR.SetDlci(getDlci(signal.pdu));    // 切换前DLCI
                pUserInfo->TDR.SetBvci(getBvci(signal.pdu));    // 切换前BVCI
                pUserInfo->TDR.SetTlli(getCurTlli(signal.pdu)); // tlli
                pUserInfo->TDR.SetCgi(getCgi(signal.pdu));      // 切换前CGI

            }
            break;
            case 0x5a: //PS_HANDOVER_REQUIRED_ACK
            {
                //SGSN => old BSS
            }
            break;
            case 0x5b: //PS_HANDOVER_REQUIRED_NACK
            {
            }
            break;
            case 0x5c: //PS_HANDOVER_REQUEST
            {
            }
            break;
            case 0x5d: //PS_HANDOVER_REQUEST_ACK
            {
            }
            break;
            case 0x5e: //PS_HANDOVER_REQUEST_NACK
            {
            }
            break;
            case 0x91: //PS_HANDOVER_COMPLETE
            {
            }
            break;
            case 0x92: //PS_HANDOVER_CANCEL
            {
            }
            break;
            //@zh add
    }
}
QString Solid::Control::ModemGsmCardInterface::getImsi() const
{
    Q_D(const ModemGsmCardInterface);
    return_SOLID_CALL(Ifaces::ModemGsmCardInterface *, d->backendObject(), QString(), getImsi());
}