ANSC_STATUS
CcspCwmpsoAddCwmpEvent
    (
        ANSC_HANDLE                 hThisObject,
        ANSC_HANDLE                 hCwmpEvent,
        BOOL                        bConnectNow
    )
{
    ANSC_STATUS                     returnStatus       = ANSC_STATUS_SUCCESS;
    PCCSP_CWMP_SESSION_OBJECT       pMyObject          = (PCCSP_CWMP_SESSION_OBJECT   )hThisObject;
    PCCSP_CWMP_PROCESSOR_OBJECT     pCcspCwmpProcessor = (PCCSP_CWMP_PROCESSOR_OBJECT )pMyObject->hCcspCwmpProcessor;
    PCCSP_CWMP_EVENT                pCcspCwmpEvent     = (PCCSP_CWMP_EVENT           )hCwmpEvent;
    PCCSP_CWMP_EVENT                pCcspCwmpEventExist= (PCCSP_CWMP_EVENT           )NULL;
    BOOL                            bExist             = FALSE;
    ULONG                           i                  = 0;

    if ( pMyObject->EventCount >= CCSP_CWMPSO_MAX_EVENT_NUMBER )
    {
        CcspCwmpFreeEvent(pCcspCwmpEvent);
	}
	else
	{
        /*
         *  Bin Zhu updated here on 12/18/2006
         *  According to WT151, for all the single event (starts with a number "0" - "9"),
         *  If there's only already in the array, the new one will be discarded.
         */
        if( pCcspCwmpEvent->EventCode[0] >= '0' && pCcspCwmpEvent->EventCode[0] <= '9')
        {
            for( i = 0; i < pMyObject->EventCount; i ++)
            {
                pCcspCwmpEventExist = (PCCSP_CWMP_EVENT)pMyObject->EventArray[i];

                if( AnscEqualString(pCcspCwmpEvent->EventCode, pCcspCwmpEventExist->EventCode, TRUE))
                {
                    bExist = TRUE;

                    CcspTr069PaTraceWarning(("The event '%s' is already there, discarded.\n", pCcspCwmpEvent->EventCode));

                    break;
                }
            }
        } 
        else 
        if ( pCcspCwmpEvent->EventCode[0] >= 'M' )
        {
            for( i = 0; i < pMyObject->EventCount; i ++)
            {
                pCcspCwmpEventExist = (PCCSP_CWMP_EVENT)pMyObject->EventArray[i];

                if ( AnscEqualString(pCcspCwmpEvent->EventCode, pCcspCwmpEventExist->EventCode, TRUE) &&
                     ( (!pCcspCwmpEvent->CommandKey && !pCcspCwmpEventExist->CommandKey) || 
                        (pCcspCwmpEvent->CommandKey && pCcspCwmpEventExist->CommandKey &&
                         AnscEqualString(pCcspCwmpEvent->CommandKey, pCcspCwmpEventExist->CommandKey, TRUE)) ) )
                {
                    bExist = TRUE;

                    CcspTr069PaTraceWarning
                        ((
                            "The event '%s' with CommandKey '%s' is already there, discarded.\n", 
                            pCcspCwmpEvent->EventCode,
                            pCcspCwmpEvent->CommandKey
                        ));

                    break;
                }
            }
        }

        if( !bExist )
        {
  		    pMyObject->EventArray[pMyObject->EventCount++] = (ANSC_HANDLE)pCcspCwmpEvent;
            CcspTr069PaTraceDebug(("<RT> Event '%s' with CommandKey '%s' added at location '%d'\n",
                                   pCcspCwmpEvent->EventCode, pCcspCwmpEvent->CommandKey, pMyObject->EventCount));
        }
        else
        {
            CcspCwmpFreeEvent(pCcspCwmpEvent);
        }
	}

    if ( bConnectNow )
    {
		PANSC_TIMER_DESCRIPTOR_OBJECT   pDelayedActiveNotifTimerObj
                                                        = (PANSC_TIMER_DESCRIPTOR_OBJECT)pMyObject->hDelayedActiveNotifTimerObj;
    	PCCSP_CWMP_PROCESSOR_PROPERTY   pProperty       = (PCCSP_CWMP_PROCESSOR_PROPERTY)&pCcspCwmpProcessor->Property;
		BOOL							bInformDelayed  = FALSE;
        PCCSP_CWMP_EVENT                pFirstEvent     = (PCCSP_CWMP_EVENT)pMyObject->EventArray[0];
	
		/* Active Notification Throttling */	
		if ( pMyObject->EventCount == 1 /* "4 VALUE CHANGE" event is the only one to trigger Inform */ && 
			 AnscEqualString(pFirstEvent->EventCode, CCSP_CWMP_INFORM_EVENT_NAME_ValueChange, TRUE) &&
			 pProperty->DefActiveNotifThrottle != 0 && 
			 pProperty->LastActiveNotifTime != 0 )
		{
			/* calculate the delay inform timer interval */
			ULONG						ulTimeNow = AnscGetTickInSeconds();
			ULONG						ulDelta   = 0;
			ULONG						ulInterval= 0;

			if ( ulTimeNow >= pProperty->LastActiveNotifTime )
			{
				ulDelta = ulTimeNow - pProperty->LastActiveNotifTime;
			}
			else
			{
				ulDelta = 0xFFFFFFFF - pProperty->LastActiveNotifTime + ulTimeNow;
			}

			if ( ulDelta < pProperty->DefActiveNotifThrottle )
			{
				bInformDelayed = TRUE;

				ulInterval = pProperty->DefActiveNotifThrottle - ulDelta;
 
    			CcspTr069PaTraceDebug(("Active notification will be delayed by %u seconds\n", ulInterval));

                if ( !pMyObject->bDelayedActiveNotifTimerScheduled )
                {
		            pDelayedActiveNotifTimerObj->SetInterval((ANSC_HANDLE)pDelayedActiveNotifTimerObj, ulInterval * 1000);
	    	        pDelayedActiveNotifTimerObj->Start((ANSC_HANDLE)pDelayedActiveNotifTimerObj);
    				pMyObject->bDelayedActiveNotifTimerScheduled = TRUE;
                }
 			}
		}


		if ( !bInformDelayed )
		{
            ULONG                   ulActiveSessions    = pCcspCwmpProcessor->GetActiveWmpSessionCount((ANSC_HANDLE)pCcspCwmpProcessor, TRUE);

            if ( ulActiveSessions == 0 )
            {
        	    pMyObject->SessionState = CCSP_CWMPSO_SESSION_STATE_connectNow;
    	        returnStatus            =
        	        pCcspCwmpProcessor->SignalSession
            	        (
                	        (ANSC_HANDLE)pCcspCwmpProcessor,
                    	    (ANSC_HANDLE)pMyObject
	                    );
            }
            else
            {
                pMyObject->bInformWhenActive = TRUE;
            }
		}
    }

    return 	returnStatus; 
}
ANSC_STATUS
CcspCwmpsoConnectToAcs
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus       = ANSC_STATUS_SUCCESS;
    PCCSP_CWMP_SESSION_OBJECT        pMyObject          = (PCCSP_CWMP_SESSION_OBJECT   )hThisObject;
    PCCSP_CWMP_ACS_CONNECTION_OBJECT     pCcspCwmpAcsConnection = (PCCSP_CWMP_ACS_CONNECTION_OBJECT)pMyObject->hCcspCwmpAcsConnection;
    PCCSP_CWMP_CPE_CONTROLLER_OBJECT     pCcspCwmpCpeController = (PCCSP_CWMP_CPE_CONTROLLER_OBJECT)pMyObject->hCcspCwmpCpeController;
    PCCSP_CWMP_PROCESSOR_OBJECT      pCcspCwmpProcessor  = (PCCSP_CWMP_PROCESSOR_OBJECT )pMyObject->hCcspCwmpProcessor;
    char*                           pAcsUrl            = (char*                      )NULL;
    char*                           pAcsUsername       = (char*                      )NULL;
    char*                           pAcsPassword       = (char*                      )NULL;

    pAcsUrl      = pCcspCwmpProcessor->GetAcsUrl     ((ANSC_HANDLE)pCcspCwmpProcessor);
    pAcsUsername = pCcspCwmpProcessor->GetAcsUsername((ANSC_HANDLE)pCcspCwmpProcessor);
    pAcsPassword = pCcspCwmpProcessor->GetAcsPassword((ANSC_HANDLE)pCcspCwmpProcessor);

	if ( !pAcsUrl )
	{
		returnStatus = ANSC_STATUS_NOT_READY;

		goto  EXIT1;
	}
	else
	{
		pCcspCwmpAcsConnection->SetAcsUrl  ((ANSC_HANDLE)pCcspCwmpAcsConnection, pAcsUrl     );
		pCcspCwmpAcsConnection->SetUsername((ANSC_HANDLE)pCcspCwmpAcsConnection, pAcsUsername);
		pCcspCwmpAcsConnection->SetPassword((ANSC_HANDLE)pCcspCwmpAcsConnection, pAcsPassword);
	}

    if ( pAcsUrl ) 
    {
        CcspTr069PaFreeMemory(pAcsUrl);
    }

    if ( pAcsUsername )
    {
        CcspTr069PaFreeMemory(pAcsUsername);
    }

    if ( pAcsPassword )
    {
        CcspTr069PaFreeMemory(pAcsPassword);
    }

    if (!pCcspCwmpAcsConnection->bActive )
    {
		returnStatus = pCcspCwmpAcsConnection->Connect((ANSC_HANDLE)pCcspCwmpAcsConnection);
	}

    if ( returnStatus == ANSC_STATUS_SUCCESS )
    {
        /*
         * Bin update on 07/08/2007
         *
         * We don't want to lock write access at the beginning of the session, we
         * are supposed to do it after we get a success InformResponse.
         */
        if( FALSE )
        {
            pMyObject->SessionState = CCSP_CWMPSO_SESSION_STATE_abort;
            returnStatus            =
                pCcspCwmpProcessor->SignalSession
                    (
                        (ANSC_HANDLE)pCcspCwmpProcessor,
                        (ANSC_HANDLE)pMyObject
                    );

            return  ANSC_STATUS_NOT_READY;
        }

        pMyObject->bActive      = TRUE;
        pMyObject->SessionState = CCSP_CWMPSO_SESSION_STATE_connected;
        returnStatus            =
            pCcspCwmpProcessor->SignalSession
                (
                    (ANSC_HANDLE)pCcspCwmpProcessor,
                    (ANSC_HANDLE)pMyObject
                );
    }


    /******************************************************************
                GRACEFUL ROLLBACK PROCEDURES AND EXIT DOORS
    ******************************************************************/

EXIT1:

    return  returnStatus;
}