ANSC_STATUS
CcspCwmpAcscoHttpBspNotify
    (
        ANSC_HANDLE                 hThisObject,
        ULONG                       ulEvent,
        ULONG                       ulError,
        ANSC_HANDLE                 hReqContext,
        ANSC_HANDLE                 hBmoReq,
        ANSC_HANDLE                 hBmoRep
    )
{
    ANSC_STATUS                      returnStatus           = ANSC_STATUS_SUCCESS;
    PANSC_ACS_INTERN_HTTP_CONTENT    pHttpGetReq            = (PANSC_ACS_INTERN_HTTP_CONTENT )hReqContext;
    PCCSP_CWMP_ACS_CONNECTION_OBJECT pMyObject              = (PCCSP_CWMP_ACS_CONNECTION_OBJECT)hThisObject;
    PCCSP_CWMP_SESSION_OBJECT        pWmpSession            = (PCCSP_CWMP_SESSION_OBJECT   )pMyObject->hCcspCwmpSession;
    PCCSP_CWMP_CPE_CONTROLLER_OBJECT pCcspCwmpCpeController = (PCCSP_CWMP_CPE_CONTROLLER_OBJECT)pWmpSession->hCcspCwmpCpeController;
    PCCSP_CWMP_STAT_INTERFACE        pCcspCwmpStatIf        = (PCCSP_CWMP_STAT_INTERFACE)pCcspCwmpCpeController->hCcspCwmpStaIf;
    PHTTP_BMO_REP_OBJECT             pHttpBmoRep            = (PHTTP_BMO_REP_OBJECT      )hBmoRep;

    switch ( ulEvent )
    {
        case    HTTP_BSP_EVENT_BAD_REQUEST :
        case    HTTP_BSP_EVENT_CANNOT_RESOLVE_NAME :
        case    HTTP_BSP_EVENT_SERVER_UNAVAILABLE :
        case    HTTP_BSP_EVENT_NETWORK_FAILURE :
        case    HTTP_BSP_EVENT_TIMEOUT :

                if( pHttpGetReq != NULL && pHttpGetReq->CompleteStatus == ANSC_STATUS_RESET_SESSION)
                {
                    break;
                }

                if( pHttpGetReq && pHttpGetReq->ulContentSize == 0)
                {
                    pHttpGetReq->CompleteStatus = ANSC_STATUS_FAILURE;

                    AnscSetEvent(&pHttpGetReq->CompleteEvent);
                }

                CcspTr069PaTraceDebug(("HttpClient Notify: %d\n", (int)ulEvent));

                if( pCcspCwmpStatIf)
                {
                    pCcspCwmpStatIf->IncTcpFailure(pCcspCwmpStatIf->hOwnerContext);
                }

                CcspCwmpAcscoHttpSessionClosed(hThisObject);

                break;

        case    HTTP_BSP_EVENT_SOCKET_CLOSED:

                /*
                 * During the test with Motive ACS, we observed that the web server
                 * close the connection after sending chanllenge back, which is an option.
                 *
                 * In that case, we need to start a new session and send back the authentication
                 * information.
                 */
                if( pHttpGetReq)
                {
                    char*           pHeaderLocation = NULL;
                    
                    if ( pHttpBmoRep )
                    {
                        pHeaderLocation = pHttpBmoRep->GetHeaderValueByName((ANSC_HANDLE)pHttpBmoRep, "Location");
                    }

                    if ( pHeaderLocation && AnscSizeOfString(pHeaderLocation) != 0 )
                    {
                        ULONG       ulCode = pHttpBmoRep->GetCode((ANSC_HANDLE)pHttpBmoRep);
                        CcspTr069PaTraceInfo(("ACS URL moved (HTTP code=%u) to: %s\n", ulCode, pHeaderLocation));

                        pHttpGetReq->ulContentSize = AnscSizeOfString(pHeaderLocation);
                        pHttpGetReq->pContent      = CcspTr069PaCloneString(pHeaderLocation);
                        pHttpGetReq->bIsRedirect   = TRUE;
                    }

                    pHttpGetReq->CompleteStatus = ANSC_STATUS_RESET_SESSION;

                    AnscSetEvent(&pHttpGetReq->CompleteEvent);
                }

                CcspTr069PaTraceDebug(("HttpClient Notify: SOCKET CLOSED\n"));

                /* CcspCwmpAcscoHttpSessionClosed(hThisObject); */

                break;

        case HTTP_BSP_EVENT_TLS_TIMEOUT:
        case HTTP_BSP_EVENT_TLS_ERROR:

                CcspTr069PaTraceDebug(("HttpClient TLS Notify: %d\n", ulEvent));

                if( pCcspCwmpStatIf)
                {
                    pCcspCwmpStatIf->IncTlsFailure(pCcspCwmpStatIf->hOwnerContext);
                }

                if ( pHttpGetReq )
                {
                    pHttpGetReq->CompleteStatus = ANSC_STATUS_FAILURE;
                    AnscSetEvent(&pHttpGetReq->CompleteEvent);
                }

                break;


        default :

                CcspTr069PaTraceDebug(("HttpClient Notify: %d\n", ulEvent));

                if ( pHttpGetReq )
                {
                    pHttpGetReq->CompleteStatus = ANSC_STATUS_FAILURE;
                    AnscSetEvent(&pHttpGetReq->CompleteEvent);
                }

                break;
    }

    return  ANSC_STATUS_SUCCESS;
}
ANSC_STATUS
CcspCwmpAcscoHttpBspBrowse
    (
        ANSC_HANDLE                 hThisObject,
        ANSC_HANDLE                 hBmoReq,
        ANSC_HANDLE                 hBmoRep,
        ANSC_HANDLE                 hReqContext
    )
{
    ANSC_STATUS                     returnStatus      = ANSC_STATUS_SUCCESS;
    PCCSP_CWMP_ACS_CONNECTION_OBJECT pMyObject         = (PCCSP_CWMP_ACS_CONNECTION_OBJECT)hThisObject;
    PHTTP_BMO_REQ_OBJECT            pHttpBmoReq       = (PHTTP_BMO_REQ_OBJECT      )hBmoReq;
    PHTTP_BMO_REP_OBJECT            pHttpBmoRep       = (PHTTP_BMO_REP_OBJECT      )hBmoRep;
    PANSC_ACS_INTERN_HTTP_CONTENT   pHttpGetReq       = (PANSC_ACS_INTERN_HTTP_CONTENT )hReqContext;
    PHTTP_RESPONSE_INFO             pHttpRepInfo      = (PHTTP_RESPONSE_INFO       )pHttpBmoRep->GetRepInfo ((ANSC_HANDLE)pHttpBmoRep);
    ULONG                           ulResponseSize    = (ULONG                     )pHttpBmoRep->GetBodySize((ANSC_HANDLE)pHttpBmoRep);
    char*                           pHttpResponse     = (char*                     )NULL;
    char*                           pHeaderLocation   = NULL;
    char*                           pCookie           = NULL;
    ULONG                           ulCode            = 0;
    char*                           pCookieHeader     = NULL;
    ULONG                           ulCookieIndex     = 0;
    BOOL                            bCookiesRemoved   = FALSE;

    if ( pHttpGetReq == NULL)
    {
        return ANSC_STATUS_FAILURE;
    }

    ulCode = pHttpBmoRep->GetCode((ANSC_HANDLE)pHttpBmoRep);

    if( HTTP_STATUS_NO_CONTENT == ulCode) /* ACS has nothing to say */
    {
        if( pHttpGetReq != NULL)
        {
            pHttpGetReq->ulContentSize = 0;
            pHttpGetReq->pContent      = NULL;
            pHttpGetReq->bIsRedirect   = FALSE;
        }

        returnStatus = ANSC_STATUS_SUCCESS;

        goto EXIT1;
    }
    else if( HTTP_STATUS_MOVED_PERMANENTLY != ulCode &&
             HTTP_STATUS_FOUND != ulCode             &&
             HTTP_STATUS_OK != ulCode                &&
             HTTP_STATUS_UNAUTHORIZED != ulCode		 &&
			 HTTP_STATUS_TEMP_REDIRECT != ulCode
           )
    {
        returnStatus = ANSC_STATUS_FAILURE;

        CcspTr069PaTraceDebug(("HttpClient returned code: %d\n", (int)ulCode));

        goto  EXIT1;
    }

    /* save Authorization header value */
    if ( TRUE )
    {
        char*                       pAuthHeaderValue   = NULL;

        /* Authorization header in request */
        pAuthHeaderValue = pHttpBmoReq->GetHeaderValueById((ANSC_HANDLE)pHttpBmoReq, HTTP_HEADER_ID_AUTHORIZATION);

        if ( pMyObject->AuthHeaderValue ) CcspTr069PaFreeMemory(pMyObject->AuthHeaderValue);
        pMyObject->AuthHeaderValue = CcspTr069PaCloneString(pAuthHeaderValue);
    }

    /* look for Set-Cookie headers */
    pCookie = pHttpBmoRep->GetHeaderValueById2((ANSC_HANDLE)pHttpBmoRep, HTTP_HEADER_ID_SET_COOKIE2, ulCookieIndex);

    if ( pCookie && AnscSizeOfString(pCookie) > 0 )
    {
        /*
        pMyObject->RemoveCookies((ANSC_HANDLE)pMyObject);
        bCookiesRemoved = TRUE;
        */

        while ( pCookie != NULL && AnscSizeOfString(pCookie) > 0)
        {
            pCookieHeader = CcspTr069PaAllocateMemory(AnscSizeOfString(pCookie) + 16);

            if ( pCookieHeader )
                _ansc_sprintf(pCookieHeader, "Set-Cookie2: %s", pCookie);

            pMyObject->AddCookie((ANSC_HANDLE)pMyObject, pCookieHeader);
            CcspTr069PaFreeMemory(pCookieHeader);

            pCookie = pHttpBmoRep->GetHeaderValueById2((ANSC_HANDLE)pHttpBmoRep, HTTP_HEADER_ID_SET_COOKIE2, ++ulCookieIndex);
        }
    }

    /* If Set-Cookie and Set-Cookie2 co-exist happily, we save them all */
    ulCookieIndex = 0;
    pCookie = pHttpBmoRep->GetHeaderValueById2((ANSC_HANDLE)pHttpBmoRep, HTTP_HEADER_ID_SET_COOKIE, ulCookieIndex);

    if( pCookie != NULL && AnscSizeOfString(pCookie) > 0)
    {
        /*
        if ( !bCookiesRemoved )
        {
            pMyObject->RemoveCookies((ANSC_HANDLE)pMyObject);
            bCookiesRemoved = TRUE;
        }
        */

        while ( pCookie && AnscSizeOfString(pCookie) )
        {
            pCookieHeader = CcspTr069PaAllocateMemory(AnscSizeOfString(pCookie) + 16);

            if ( pCookieHeader )
                _ansc_sprintf(pCookieHeader, "Set-Cookie: %s", pCookie);

            pMyObject->AddCookie((ANSC_HANDLE)pMyObject, pCookieHeader);
            CcspTr069PaFreeMemory(pCookieHeader);

            pCookie = pHttpBmoRep->GetHeaderValueById2((ANSC_HANDLE)pHttpBmoRep, HTTP_HEADER_ID_SET_COOKIE, ++ulCookieIndex);
        }
    }

    /*
    if ( !bCookiesRemoved )
    {
        CcspTr069PaTraceDebug(("No Cookie in the response.\n"));

        if( pMyObject->NumCookies != 0)
        {
            for ( i = 0; i < pMyObject->NumCookies; i ++ )
            {
                CcspTr069PaTraceDebug(("Keep the old cookie: %s\n", pMyObject->Cookies[i]));
            }
        }
        else
        {
            CcspTr069PaTraceDebug(("???No cookie exists...\n"));
        }
    }
    */

    if( HTTP_STATUS_UNAUTHORIZED == ulCode)
    {
        /* make sure if server sends back challenge, terminates the session if otherwise */
        char*                       pWwwAuth = NULL;

        pHttpGetReq->bUnauthorized = TRUE;
        
        pWwwAuth = pHttpBmoRep->GetHeaderValueByName((ANSC_HANDLE)pHttpBmoRep, "WWW-Authenticate");
        if ( pWwwAuth )
        {
            returnStatus = ANSC_STATUS_DO_IT_AGAIN; /* ANSC_STATUS_SUCCESS; */
        }
        else
        {
            returnStatus = ANSC_STATUS_FAILURE;
        }

        goto EXIT1;
    }

    if( ulCode == HTTP_STATUS_MOVED_PERMANENTLY || HTTP_STATUS_FOUND == ulCode || HTTP_STATUS_TEMP_REDIRECT == ulCode)
    {
        pHeaderLocation     = pHttpBmoRep->GetHeaderValueByName((ANSC_HANDLE)pHttpBmoRep, "Location"     );

        if( pHeaderLocation == NULL || AnscSizeOfString(pHeaderLocation) == 0)
        {
            returnStatus = ANSC_STATUS_FAILURE;

            goto  EXIT1;
        }

        CcspTr069PaTraceInfo(("ACS URL moved (HTTP code=%u) to: %s\n", ulCode, pHeaderLocation));

        pHttpGetReq->ulContentSize = AnscSizeOfString(pHeaderLocation);
        pHttpGetReq->pContent      = CcspTr069PaCloneString(pHeaderLocation);
        pHttpGetReq->bIsRedirect   = TRUE;

        /* notify underlying HTTP Webc Transaction object to clearn request
         * otherwise, in case ACS closes the socket first, we will get notified
         * again and current session will be terminated prematurely.
         */
        returnStatus = ANSC_STATUS_NO_MORE_DATA;
    }
    else
    {
        if ( ulResponseSize == 0 )
        {
             returnStatus = ANSC_STATUS_FAILURE;

            goto  EXIT1;
        }
        else
        {
            pHttpResponse = (char*)CcspTr069PaAllocateMemory(ulResponseSize + 1);  /* we must leave room for the NULL terminator */

            if ( !pHttpResponse )
            {
                returnStatus = ANSC_STATUS_RESOURCES;

                goto  EXIT1;
            }
            else
            {
                returnStatus =
                    pHttpBmoRep->CopyBodyFrom
                        (
                            (ANSC_HANDLE)pHttpBmoRep,
                            pHttpResponse,
                            &ulResponseSize
                        );
            }
        }

        pHttpGetReq->ulContentSize = ulResponseSize;
        pHttpGetReq->pContent      = (PVOID)pHttpResponse;
        pHttpGetReq->bIsRedirect   = FALSE;
    }

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

EXIT1:

    if ( pHttpGetReq )
    {
        pHttpGetReq->CompleteStatus = 
            (returnStatus == ANSC_STATUS_DO_IT_AGAIN || returnStatus == ANSC_STATUS_NO_MORE_DATA) ? ANSC_STATUS_SUCCESS : returnStatus;

        AnscSetEvent(&pHttpGetReq->CompleteEvent);
    }

    return  returnStatus;
}