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

    prototype:

        ANSC_STATUS
        CcspCwmpSoappoUtilGetParamAttribute
            (
                ANSC_HANDLE                 hXmlHandle,
                ANSC_HANDLE                 hAttrHandle
            );

    description:

        This function is called to get the parameter attribute from the
        xml handle.

    argument:
                ANSC_HANDLE                 hXmlHandle,
                The XML node;

                ANSC_HANDLE                 hAttrHandle
                The parameter attribute handle

    return:     the status of the operation.

**********************************************************************/
ANSC_STATUS
CcspCwmpSoappoUtilGetParamAttribute
    (
        ANSC_HANDLE                 hXmlHandle,
        ANSC_HANDLE                 hAttrHandle
    )
{
    PANSC_XML_DOM_NODE_OBJECT       pXmlNode     = (PANSC_XML_DOM_NODE_OBJECT)hXmlHandle;
    PANSC_XML_DOM_NODE_OBJECT       pListNode    = (PANSC_XML_DOM_NODE_OBJECT)NULL;
    PANSC_XML_DOM_NODE_OBJECT       pChildNode   = (PANSC_XML_DOM_NODE_OBJECT)NULL;
    PCCSP_CWMP_SET_PARAM_ATTRIB     pParamAttr   = (PCCSP_CWMP_SET_PARAM_ATTRIB)hAttrHandle;
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    CHAR                            pValue[2048] = { 0 };
    PCHAR                           pBegin       = NULL;
    ULONG                           length       = 2048;
    ULONG                           uLeft        = 2048;

    /***************************************************************************
    * Argument     | Type         | Description                               *
    ***************************************************************************
    * Name         | string(256)  | This is the name of a Parameter.          *
    *-------------------------------------------------------------------------*
    * Notification | boolean      | notification update                      .*
    * Change       |              |     .                                     *
    *-------------------------------------------------------------------------*
    * Notification | int(0:2)     | notification value                       .*
    *-------------------------------------------------------------------------*
    * AccessList   | boolean      | change accesslist or not                 .*
    * Change       |              |     .                                     *
    *-------------------------------------------------------------------------*
    * AccesList    | string(64)[] | array of access list                     .*
    ***************************************************************************/

    /*
     * Get the name first;
     */
    pChildNode = (PANSC_XML_DOM_NODE_OBJECT)
		AnscXmlDomNodeGetHeadChild(pXmlNode);

    if( pChildNode == NULL)
    {
        CcspTr069PaTraceError(("Invalid arguments for ParameterAttributeStruct.\n"));

        return ANSC_STATUS_FAILURE;
    }

    length = 256;

    returnStatus =
    	AnscXmlDomNodeGetDataString
            (
                pChildNode,
                NULL,
                pValue,
                &length
            );

    if( returnStatus != ANSC_STATUS_SUCCESS)
    {
        CcspTr069PaTraceError(("Failed to get the parameter name.\n"));

        return returnStatus;
    }

    pParamAttr->Name = CcspTr069PaCloneString(pValue);

    /*
     * Get the notification change flag
     */
    pChildNode = (PANSC_XML_DOM_NODE_OBJECT)
		AnscXmlDomNodeGetNextChild(pXmlNode, pChildNode);

    if( pChildNode == NULL)
    {
        CcspTr069PaTraceError(("Invalid arguments for ParameterAttributeStruct.\n"));

        return ANSC_STATUS_FAILURE;
    }

    returnStatus =
    	AnscXmlDomNodeGetDataBoolean
            (
                pChildNode,
                NULL,
                &pParamAttr->bNotificationChange
            );

    if( returnStatus != ANSC_STATUS_SUCCESS)
    {
        CcspTr069PaTraceError(("Failed to get the notification flag.\n"));

        return returnStatus;
    }

    /*
     * Get the notificateion value
     */
    pChildNode = (PANSC_XML_DOM_NODE_OBJECT)
		AnscXmlDomNodeGetNextChild(pXmlNode, pChildNode);

    if( pChildNode == NULL)
    {
        CcspTr069PaTraceError(("Invalid arguments for ParameterAttributeStruct.\n"));

        return ANSC_STATUS_FAILURE;
    }

    returnStatus =
    	AnscXmlDomNodeGetDataUlong
            (
                pChildNode,
                NULL,
                &pParamAttr->Notification
            );

    if( returnStatus != ANSC_STATUS_SUCCESS)
    {
        CcspTr069PaTraceError(("Failed to get the notification value.\n"));

        return returnStatus;
    }

    /*
     * Get the accesslist change flag
     */
    pChildNode = (PANSC_XML_DOM_NODE_OBJECT)
		AnscXmlDomNodeGetNextChild(pXmlNode, pChildNode);

    if( pChildNode == NULL)
    {
        CcspTr069PaTraceError(("Invalid arguments for ParameterAttributeStruct.\n"));

        return ANSC_STATUS_FAILURE;
    }

    returnStatus =
    	AnscXmlDomNodeGetDataBoolean
            (
                pChildNode,
                NULL,
                &pParamAttr->bAccessListChange
            );

    if( returnStatus != ANSC_STATUS_SUCCESS)
    {
        CcspTr069PaTraceError(("Failed to get the AccessListChange flag.\n"));

        return returnStatus;
    }

    /*
     * Get the accesslist
     */
    pParamAttr->AccessList = NULL;

    pListNode = (PANSC_XML_DOM_NODE_OBJECT)
		AnscXmlDomNodeGetNextChild(pXmlNode, pChildNode);

    if( pListNode == NULL)
    {
        return ANSC_STATUS_SUCCESS;
    }

    length                 = 2048;
    AnscZeroMemory(pValue, length);

    pBegin                 = pValue;

    pChildNode = (PANSC_XML_DOM_NODE_OBJECT)
		AnscXmlDomNodeGetHeadChild(pListNode);

    while( pChildNode != NULL)
    {
        if( pBegin != pValue)
        {
            AnscCopyMemory(pBegin, CCSP_CWMP_COMMA, AnscSizeOfString(CCSP_CWMP_COMMA));
            pBegin += AnscSizeOfString(CCSP_CWMP_COMMA);
            uLeft  -= AnscSizeOfString(CCSP_CWMP_COMMA);
            length  = uLeft;
        }

        returnStatus =
        	AnscXmlDomNodeGetDataString
                (
                    pChildNode,
                    NULL,
                    pBegin,
                    &length
                );

        if( returnStatus != ANSC_STATUS_SUCCESS)
        {
            CcspTr069PaTraceError(("Failed to get the AccessList value.\n"));

            return returnStatus;
        }

        pBegin += length;
        uLeft  -= length;
        length  = uLeft;


        pChildNode = (PANSC_XML_DOM_NODE_OBJECT)
			AnscXmlDomNodeGetNextChild(pListNode, pChildNode);
    }

    if( pBegin != pValue)
    {
        pParamAttr->AccessList = CcspTr069PaCloneString(pValue);
    }

    return returnStatus;
}
ANSC_STATUS
CcspCwmpTcpcrhoEngage
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus  = ANSC_STATUS_SUCCESS;
    PCCSP_CWMP_TCPCR_HANDLER_OBJECT      pMyObject     = (PCCSP_CWMP_TCPCR_HANDLER_OBJECT    )hThisObject;
    PCCSP_CWMP_TCPCR_HANDLER_PROPERTY    pProperty     = (PCCSP_CWMP_TCPCR_HANDLER_PROPERTY  )&pMyObject->Property;
    PANSC_DAEMON_SERVER_TCP_OBJECT  pTcpServer    = (PANSC_DAEMON_SERVER_TCP_OBJECT)pMyObject->hTcpServer;
    ULONG                           ulEngineCount = 1;
    ULONG                           ulSocketCount = 1;
    ULONG                           ulTcpDsoMode  = ANSC_DSTO_MODE_EVENT_SYNC | ANSC_DSTO_MODE_FOREIGN_BUFFER | ANSC_DSTO_MODE_COMPACT;

    if ( pMyObject->bActive )
    {
        return  ANSC_STATUS_SUCCESS;
    }
    else
    {
        pMyObject->bActive = TRUE;
    }

    returnStatus = pMyObject->CreateTcpServers((ANSC_HANDLE)pMyObject);
    if ( returnStatus != ANSC_STATUS_SUCCESS )
    {
        CcspTr069PaTraceDebug(("Create TCP server failed\n"));

        pMyObject->bActive = FALSE;
        return  returnStatus;
    }

    if ( pProperty->ServerMode & CCSP_CWMP_TCPCR_HANDLER_MODE_useXsocket )
    {
        ulTcpDsoMode |= ANSC_DSTO_MODE_XSOCKET;
    }

    ulEngineCount = 1;
    ulSocketCount = 4;

    pTcpServer    = (PANSC_DAEMON_SERVER_TCP_OBJECT)pMyObject->hTcpServer;

    if ( pTcpServer )
    {
#ifdef _ANSC_IPV6_COMPATIBLE_
        CcspTr069PaTraceDebug(("Tcp host addr=%s:%d\n", 
                               pProperty->HostAddr,
                               pProperty->HostPort));
        AnscCopyString(pTcpServer->HostName, pProperty->HostAddr);
#else
        CcspTr069PaTraceDebug(("Tcp host addr=%d.%d.%d.%d:%d\n", 
                               pProperty->HostAddress.Dot[0],
                               pProperty->HostAddress.Dot[1],
                               pProperty->HostAddress.Dot[2],
                               pProperty->HostAddress.Dot[3],
                               pProperty->HostPort));

        pTcpServer->SetHostAddress   ((ANSC_HANDLE)pTcpServer, pProperty->HostAddress.Dot);
#endif
        pTcpServer->SetHostPort      ((ANSC_HANDLE)pTcpServer, pProperty->HostPort       );
        pTcpServer->SetMaxMessageSize((ANSC_HANDLE)pTcpServer, CCSP_CWMP_TCPCR_MAX_MSG_SIZE   );
        pTcpServer->SetEngineCount   ((ANSC_HANDLE)pTcpServer, ulEngineCount             );
        pTcpServer->SetMinSocketCount((ANSC_HANDLE)pTcpServer, 0                         );
        pTcpServer->SetMaxSocketCount((ANSC_HANDLE)pTcpServer, ulSocketCount             );
        pTcpServer->SetMode          ((ANSC_HANDLE)pTcpServer, ulTcpDsoMode              );

        returnStatus = pTcpServer->Engage((ANSC_HANDLE)pTcpServer);
        if ( returnStatus != ANSC_STATUS_SUCCESS )
        {
            CcspTr069PaTraceError(("CcspCwmpTcpcrhoEngage - failed to be engaged, CWMP will not run properly!\n"));
            pMyObject->bActive = FALSE;

            return  returnStatus;
        }
    }

    return  ANSC_STATUS_SUCCESS;
}
/**********************************************************************

    prototype:

        ANSC_STATUS
        CcspCwmpSoappoUtilGetParamValue
            (
                ANSC_HANDLE                 hXmlHandle,
                ANSC_HANDLE                 hParamHandle
            );

    description:

        This function is called to get the parameter value from the
        xml handle.

    argument:
                ANSC_HANDLE                 hXmlHandle,
                The XML node;

                ANSC_HANDLE                 hParamHandle
                The parameter handle

    return:     the status of the operation.

**********************************************************************/
ANSC_STATUS
CcspCwmpSoappoUtilGetParamValue
    (
        ANSC_HANDLE                 hCcspCwmpMcoIf,
        ANSC_HANDLE                 hXmlHandle,
        ANSC_HANDLE                 hParamHandle
    )
{
    PCCSP_CWMP_MCO_INTERFACE        pCcspCwmpMcoIf = (PCCSP_CWMP_MCO_INTERFACE)hCcspCwmpMcoIf;
    PANSC_XML_DOM_NODE_OBJECT       pXmlNode     = (PANSC_XML_DOM_NODE_OBJECT)hXmlHandle;
    PANSC_XML_DOM_NODE_OBJECT       pNameNode    = (PANSC_XML_DOM_NODE_OBJECT)NULL;
    PANSC_XML_DOM_NODE_OBJECT       pValueNode   = (PANSC_XML_DOM_NODE_OBJECT)NULL;
    PCCSP_CWMP_PARAM_VALUE          pCwmpParam   = (PCCSP_CWMP_PARAM_VALUE)hParamHandle;
    PSLAP_VARIABLE                  pSlapVariable= (PSLAP_VARIABLE)NULL;
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    CHAR                            pValue[1024] = { 0 };
    ULONG                           dataType     = CCSP_CWMP_TR069_DATA_TYPE_Unspecified;
    ULONG                           length       = 1024;
    ULONG                           uLongValue   = 0;
    LONG                            longValue    = 0;
    BOOL                            bBool        = FALSE;
    BOOL                            bIsInteger   = FALSE;
    PANSC_XML_ATTRIBUTE             pAttribute   = NULL;
	char*							pDataType    = NULL;
    char                            pTemp[64]    = { 0 };
    CHAR                            pHugeValue[32000]
                                                 = { 0 };  /* Config file value could be as big as 32K */

    pCwmpParam->Value          = NULL;

    /***************************************************************************
    * Argument     | Type         | Description                               *
    ***************************************************************************
    * Name         | string(256)  | This is the name of a Parameter.          *
    *-------------------------------------------------------------------------*
    * Value        | any          | Teh is the value to be set               .*
    ***************************************************************************/

    pNameNode = (PANSC_XML_DOM_NODE_OBJECT)
		AnscXmlDomNodeGetHeadChild(pXmlNode);

    pValueNode = (PANSC_XML_DOM_NODE_OBJECT)
		AnscXmlDomNodeGetTailChild(pXmlNode);

    if( pNameNode == NULL || pValueNode == NULL || pNameNode == pValueNode)
    {
        CcspTr069PaTraceError(("Invalid arguments for ParameterValueStruct.\n"));

        return ANSC_STATUS_FAILURE;
    }

    /*
     * Get the name first;
     */
    length = 256;

    returnStatus =
    	AnscXmlDomNodeGetDataString
            (
                pNameNode,
                NULL,
                pValue,
                &length
            );

    if( returnStatus != ANSC_STATUS_SUCCESS)
    {
        CcspTr069PaTraceError(("Failed to get the parameter name.\n"));

        return returnStatus;
    }

	if( length == 0)
	{
		CcspTr069PaTraceError(("Empty parameter name in SetParameterValues.\n"));

		return ANSC_STATUS_FAILURE;
	}

    pCwmpParam->Name = CcspTr069PaCloneString(pValue);

    length = 1024;
    AnscZeroMemory(pValue, length);

    pSlapVariable = (PSLAP_VARIABLE)CcspTr069PaAllocateMemory(sizeof(SLAP_VARIABLE));

    if ( !pSlapVariable )
    {
        return ANSC_STATUS_RESOURCES;
    }

    SlapInitVariable(pSlapVariable);

    pCwmpParam->Value          = pSlapVariable;

    pSlapVariable->Name        = NULL;
    pSlapVariable->ContentType = 0;
    pSlapVariable->UsageType   = 0;

    /* check the value */
    length = 32000;

    returnStatus =
        AnscXmlDomNodeGetDataString
            (
                pValueNode,
                NULL,
                pHugeValue,
                &length
            );

    if( returnStatus != ANSC_STATUS_SUCCESS)
    {
        CcspTr069PaTraceError(("Failed to get the string parameter value.\n"));

        CcspTr069PaFreeMemory(pSlapVariable);

        pCwmpParam->Value = NULL;
    }
    else
    {
        pSlapVariable->ContentType       = SLAP_CONTENT_TYPE_UNSPECIFIED;
        pSlapVariable->UsageType         = 0;
        pSlapVariable->Syntax            = SLAP_VAR_SYNTAX_string;
        pSlapVariable->Variant.varString = CcspTr069PaCloneString(pHugeValue);
    }

    pCwmpParam->Tr069DataType = CCSP_CWMP_TR069_DATA_TYPE_Unspecified;

    /* retrieve data type */
    if ( TRUE )
    {
        PANSC_XML_ATTRIBUTE         pAttribute;
        
        pCwmpParam->Tr069DataType  = pCcspCwmpMcoIf->GetParamDataType(pCcspCwmpMcoIf->hOwnerContext, pCwmpParam->Name);
        pAttribute = (PANSC_XML_ATTRIBUTE)AnscXmlDomNodeGetFirstAttr(pValueNode);
        if ( pAttribute )
        {
            char*                   pDataType;

            AnscCopyMemory(pValue, pAttribute->StringData, pAttribute->DataSize);

            pDataType = _ansc_strstr(pValue, ":");

            if ( !pDataType )
            {
                pDataType = pValue;
            }
            else
            {
                pDataType ++;
            }

            if ( AnscEqualString(pDataType, CCSP_CWMP_DATA_NAME_string, TRUE) )
            {
                pCwmpParam->Tr069DataType = CCSP_CWMP_TR069_DATA_TYPE_String;
            }
            else if ( AnscEqualString(pDataType, CCSP_CWMP_DATA_NAME_int, TRUE) )
            {
                pCwmpParam->Tr069DataType = CCSP_CWMP_TR069_DATA_TYPE_Int;
            }
            else if ( AnscEqualString(pDataType, CCSP_CWMP_DATA_NAME_unsignedInt, TRUE) )
            {
                pCwmpParam->Tr069DataType = CCSP_CWMP_TR069_DATA_TYPE_UnsignedInt;
            }
            else if ( AnscEqualString(pDataType, CCSP_CWMP_DATA_NAME_boolean, TRUE) )
            {
                pCwmpParam->Tr069DataType = CCSP_CWMP_TR069_DATA_TYPE_Boolean;
            }
            else if ( AnscEqualString(pDataType, CCSP_CWMP_DATA_NAME_dateTime, TRUE) )
            {
                pCwmpParam->Tr069DataType = CCSP_CWMP_TR069_DATA_TYPE_DateTime;
            }
            else if ( AnscEqualString(pDataType, CCSP_CWMP_DATA_NAME_base64, TRUE) )
            {
                pCwmpParam->Tr069DataType = CCSP_CWMP_TR069_DATA_TYPE_Base64;
            }
            else
            {
                pCwmpParam->Tr069DataType = CCSP_CWMP_TR069_DATA_TYPE_Unspecified;
            }
        }
    }    

    if ( pCwmpParam->Tr069DataType == CCSP_CWMP_TR069_DATA_TYPE_Unspecified )
    {
        return  ANSC_STATUS_BAD_PARAMETER;
    }

    return ANSC_STATUS_SUCCESS;
}
/**********************************************************************

    prototype:

        ANSC_STATUS
        CcspCwmpSoappoUtilGetCwmpMethodName
            (
                ULONG                       uMethod,
                BOOL                        bFromServer
                PCHAR                       pOutBuffer
            );

    description:

        This function is called to find method name based on the value.

    argument:
                ULONG                       uMethod,
                The method value;

                BOOL                        bFromServer
                It's a server side method or not

                PCHAR                       pOutBuffer
                The output method name.

    return:     the status of the operation.

**********************************************************************/
ANSC_STATUS
CcspCwmpSoappoUtilGetCwmpMethodName
    (
        ULONG                       uMethod,
        BOOL                        bFromServer,
        PCHAR                       pOutBuffer
    )
{
    if( uMethod == CCSP_CWMP_METHOD_GetRPCMethods)
    {
        AnscCopyString(pOutBuffer,"GetRPCMethods");

        return ANSC_STATUS_SUCCESS;
    }

    if(!bFromServer)
    {
        switch ( uMethod )
        {
            case CCSP_CWMP_METHOD_SetParameterValues:

                AnscCopyString(pOutBuffer,"SetParameterValues");

                break;

            case CCSP_CWMP_METHOD_GetParameterValues:

                AnscCopyString(pOutBuffer,"GetParameterValues");

                break;

            case CCSP_CWMP_METHOD_GetParameterNames:

                AnscCopyString(pOutBuffer,"GetParameterNames");

                break;

            case CCSP_CWMP_METHOD_SetParameterAttributes:

                AnscCopyString(pOutBuffer,"SetParameterAttributes");

                break;

            case CCSP_CWMP_METHOD_GetParameterAttributes:

                AnscCopyString(pOutBuffer,"GetParameterAttributes");

                break;

            case CCSP_CWMP_METHOD_AddObject:

                AnscCopyString(pOutBuffer,"AddObject");

                break;

            case CCSP_CWMP_METHOD_DeleteObject:

                AnscCopyString(pOutBuffer,"DeleteObject");

                break;

            case CCSP_CWMP_METHOD_Reboot:

                AnscCopyString(pOutBuffer,"Reboot");

                break;

            case CCSP_CWMP_METHOD_Download:

                AnscCopyString(pOutBuffer,"Download");

                break;

            case CCSP_CWMP_METHOD_Upload:

                AnscCopyString(pOutBuffer,"Upload");

                break;

            case CCSP_CWMP_METHOD_FactoryReset:

                AnscCopyString(pOutBuffer,"FactoryReset");

                break;

            case CCSP_CWMP_METHOD_GetQueuedTransfers:

                AnscCopyString(pOutBuffer,"GetQueuedTransfers");

                break;

            case CCSP_CWMP_METHOD_ScheduleInform:

                AnscCopyString(pOutBuffer,"ScheduleInform");

                break;

            case CCSP_CWMP_METHOD_SetVouchers:

                AnscCopyString(pOutBuffer,"SetVouchers");

                break;

            case CCSP_CWMP_METHOD_GetOptions:

                AnscCopyString(pOutBuffer,"GetOptions");

                break;

            default:

                CcspTr069PaTraceError(("Unknown CWMP Client method type: %d\n", uMethod));

                return ANSC_STATUS_FAILURE;
        }
    }
    else
    {
        switch ( uMethod )
        {
            case CCSP_CWMP_METHOD_Inform:

                AnscCopyString(pOutBuffer,"Inform");

                break;

            case CCSP_CWMP_METHOD_TransferComplete:

                AnscCopyString(pOutBuffer,"TransferComplete");

                break;

            case CCSP_CWMP_METHOD_RequestDownload:

                AnscCopyString(pOutBuffer,"RequestDownload");

                break;

            case CCSP_CWMP_METHOD_Kicked:

                AnscCopyString(pOutBuffer,"Kicked");

                break;

            default:

                CcspTr069PaTraceError(("Unknown CWMP Server method type: %d\n", uMethod));

                return ANSC_STATUS_FAILURE;
        }
    }

    return ANSC_STATUS_SUCCESS;
}
ANSC_STATUS
CcspCwmpTcpcrhoCreateTcpServers

    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus  = ANSC_STATUS_SUCCESS;
    PCCSP_CWMP_TCPCR_HANDLER_OBJECT      pMyObject     = (PCCSP_CWMP_TCPCR_HANDLER_OBJECT    )hThisObject;
    PCCSP_CWMP_TCPCR_HANDLER_PROPERTY    pProperty     = (PCCSP_CWMP_TCPCR_HANDLER_PROPERTY  )&pMyObject->Property;
    PANSC_DAEMON_SERVER_TCP_OBJECT  pTcpServer    = (PANSC_DAEMON_SERVER_TCP_OBJECT)pMyObject->hTcpServer;
    char  buf[64]      = {0};

    if ( pProperty->HostPort == 0 && pTcpServer )
    {
        CcspTr069PaTraceDebug(("Port is 0 on current TcpServer: Server will be removed!!!\n"));
        pTcpServer->Remove((ANSC_HANDLE)pTcpServer);
        pMyObject->hTcpServer   = (ANSC_HANDLE)NULL;
    }
    else if ( !pTcpServer && pProperty->HostPort != 0 )
    {
        if ( bIsComcastImage() ) {

           // If HostAddress value is zero, then bind the outbound interface's ip address
           if( pProperty->HostAddress.Value == 0)
           {
              CcspTr069PaTraceInfo(("%s, HostAddress value is 0\n",__FUNCTION__));
              token_t  se_token;
              int      se_fd = s_sysevent_connect(&se_token);
              if (0 > se_fd) 
              {
                 CcspTr069PaTraceError(("%s, sysevent_connect failed!!!\n",__FUNCTION__));
                 //return ERR_SYSEVENT_CONN;
              }
              else
              {
                 // Get ipv4 address from sysevent
                 if( 0 == sysevent_get(se_fd, se_token, "ipv4_wan_ipaddr", buf, sizeof(buf)) && '\0' != buf[0] )
                 {
                    CcspTr069PaTraceInfo(("%s, ipv4_wan_ipaddr got from sysevent is: %s\n",__FUNCTION__,buf));
                    pProperty->HostAddress.Value = _ansc_inet_addr(buf);
                    CcspTr069PaTraceInfo(("%s,pProperty->HostAddress.Value: %lu\n",__FUNCTION__,pProperty->HostAddress.Value));
                 }
                 else
                 {
                  // If sysevent fails, let TR69 bind on 0.0.0.0
                  CcspTr069PaTraceError(("%s, sysevent_get failed to get value of ipv4_wan_ipaddr!!!\n",__FUNCTION__));
                 }
              }
           }
       
           CcspTr069PaTraceInfo(("%s, Call AnscCreateDaemonServerTcp\n",__FUNCTION__));
        }
        pTcpServer =
            (PANSC_DAEMON_SERVER_TCP_OBJECT)AnscCreateDaemonServerTcp
                (
                    pMyObject->hContainerContext,
                    (ANSC_HANDLE)pMyObject,
                    (ANSC_HANDLE)NULL
                );

        if ( !pTcpServer )
        {
            CcspTr069PaTraceError(("Something wrong in AnscCreateDaemonServerTCP.\n"));
            return  ANSC_STATUS_RESOURCES;
        }
        else
        {
            pMyObject->hTcpServer = (ANSC_HANDLE)pTcpServer;
        }

        pTcpServer->SetWorker
            (
                (ANSC_HANDLE)pTcpServer,
                pMyObject->hDstoWorker,
                sizeof(ANSC_DSTO_WORKER_OBJECT)
            );
    }

    CcspTr069PaTraceInfo(("TCP server created successfully.\n"));

    return  ANSC_STATUS_SUCCESS;
}
/**********************************************************************

    prototype:

        ANSC_STATUS
        CcspCwmpAcscoRequestOny
            (
                ANSC_HANDLE                 hThisObject
            );

    description:

        This function is called to send the last empty request to ACS.

    argument:

                ANSC_HANDLE                 hThisObject
                The caller object.

    return:     the status of the operation;

**********************************************************************/
ANSC_STATUS
CcspCwmpAcscoRequestOnly
    (
        ANSC_HANDLE                 hThisObject
    )
{
    PCCSP_CWMP_ACS_CONNECTION_OBJECT pMyObject      = (PCCSP_CWMP_ACS_CONNECTION_OBJECT)hThisObject;

    return  pMyObject->Request((ANSC_HANDLE)pMyObject, NULL, NULL, 0, 0);

#if 0
    PHTTP_SIMPLE_CLIENT_OBJECT      pHttpClient     = (PHTTP_SIMPLE_CLIENT_OBJECT)pMyObject->hHttpSimpleClient;
    PCCSP_CWMP_SESSION_OBJECT       pWmpSession     = (PCCSP_CWMP_SESSION_OBJECT   )pMyObject->hCcspCwmpSession;
    PCCSP_CWMP_MCO_INTERFACE        pCcspCwmpMcoIf  = (PCCSP_CWMP_MCO_INTERFACE    )pWmpSession->hCcspCwmpMcoIf;
    PHTTP_HFP_INTERFACE             pHttpHfpIf      = (PHTTP_HFP_INTERFACE)pHttpClient->GetHfpIf((ANSC_HANDLE)pHttpClient);
    PHTTP_CAS_INTERFACE             pHttpCasIf      = NULL;
    PHTTP_REQUEST_URI               pHttpReqInfo    = NULL;
    ANSC_STATUS                     returnStatus    = ANSC_STATUS_SUCCESS;
    ANSC_ACS_INTERN_HTTP_CONTENT    intHttpContent  = { 0 };
    PANSC_ACS_INTERN_HTTP_CONTENT   pHttpGetReq     = &intHttpContent;
    BOOL                            bApplyTls       = FALSE;
    PCHAR                           pRequestURL     = NULL;
    PCHAR                           pTempString     = NULL;
    PHTTP_AUTH_CLIENT_OBJECT        pAuthClientObj  = NULL;
    char                            pNewUrl[257]    = { 0 };
    ULONG                           uRedirect       = 0;
    ULONG                           uMaxRedirect    = 5;

    if( pMyObject->AcsUrl == NULL || AnscSizeOfString(pMyObject->AcsUrl) <= 10 || pHttpHfpIf == NULL)
    {
        return ANSC_STATUS_NOT_READY;
    }

    CcspTr069PaTraceDebug(("CcspCwmpAcscoRequest -- AcsUrl = '%s'\n", pMyObject->AcsUrl));

    pRequestURL = pMyObject->AcsUrl;

    if ( AnscEqualString2(pRequestURL, "https", 5, FALSE) )
    {
        bApplyTls = TRUE;
    }
    else if ( AnscEqualString2(pRequestURL, "http", 4, FALSE) )
    {
        bApplyTls = FALSE;
    }
    else
    {
        return ANSC_STATUS_NOT_SUPPORTED;
    }

    pHttpCasIf  = (PHTTP_CAS_INTERFACE)pHttpClient->GetCasIf((ANSC_HANDLE)pHttpClient);

    if ( pHttpCasIf != NULL)
    {
        if( pMyObject->Username == NULL || AnscSizeOfString(pMyObject->Username) == 0)
        {
            pHttpCasIf->EnableAuth(pHttpCasIf->hOwnerContext, FALSE);
        }
        else
        {
            pHttpCasIf->EnableAuth(pHttpCasIf->hOwnerContext, TRUE);

            pAuthClientObj  = (PHTTP_AUTH_CLIENT_OBJECT)pHttpClient->GetClientAuthObj((ANSC_HANDLE)pHttpClient);

            if ( pAuthClientObj != NULL)
            {
                pAuthClientObj->SetAcmIf((ANSC_HANDLE)pAuthClientObj, (ANSC_HANDLE)pMyObject->hHttpAcmIf);
            }
            else
            {
                CcspTr069PaTraceError(("Failed to Get HttpAuthClient object.\n"));
            }
        }
    }

    pHttpReqInfo =
        (PHTTP_REQUEST_URI)pHttpHfpIf->ParseHttpUrl
            (
                pHttpHfpIf->hOwnerContext,
                pRequestURL,
                AnscSizeOfString(pRequestURL)
            );

    if ( !pHttpReqInfo )
    {
        return ANSC_STATUS_INTERNAL_ERROR;
    }

    pHttpReqInfo->Type = HTTP_URI_TYPE_ABS_PATH;


    CcspTr069PaTraceInfo(("Send empty request to now at: %u\n", (unsigned int)AnscGetTickInSeconds()));

    returnStatus =
        pHttpClient->Request
            (
                (ANSC_HANDLE)pHttpClient,
                (ULONG      )HTTP_METHOD_CODE_POST,
                (ANSC_HANDLE)pHttpReqInfo,
                (ANSC_HANDLE)NULL,
                bApplyTls
            );

    AnscSleep(500);

    CcspTr069PaFreeMemory(pHttpReqInfo);

    return returnStatus;
#endif
}
ANSC_STATUS
CcspCwmpAcscoRequest
    (
        ANSC_HANDLE                 hThisObject,
        char*                       pSoapMessage,
        char*                       pMethodName,
        ULONG                       ulReqEnvCount,
        ULONG                       ulRepEnvCount
    )
{
    PCCSP_CWMP_ACS_CONNECTION_OBJECT pMyObject      = (PCCSP_CWMP_ACS_CONNECTION_OBJECT)hThisObject;
    PHTTP_SIMPLE_CLIENT_OBJECT      pHttpClient     = (PHTTP_SIMPLE_CLIENT_OBJECT)pMyObject->hHttpSimpleClient;
    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;
	PCCSP_CWMP_CFG_INTERFACE		pCcspCwmpCfgIf	= (PCCSP_CWMP_CFG_INTERFACE)pCcspCwmpCpeController->hCcspCwmpCfgIf;
    PCCSP_CWMP_MCO_INTERFACE        pCcspCwmpMcoIf  = (PCCSP_CWMP_MCO_INTERFACE        )pWmpSession->hCcspCwmpMcoIf;
    PHTTP_HFP_INTERFACE             pHttpHfpIf      = (PHTTP_HFP_INTERFACE)pHttpClient->GetHfpIf((ANSC_HANDLE)pHttpClient);
    PHTTP_CAS_INTERFACE             pHttpCasIf      = NULL;
    PHTTP_REQUEST_URI               pHttpReqInfo    = NULL;
    ANSC_STATUS                     returnStatus    = ANSC_STATUS_SUCCESS;
    PANSC_ACS_INTERN_HTTP_CONTENT   pHttpGetReq     = &intHttpContent;
    BOOL                            bApplyTls       = FALSE;
    PCHAR                           pRequestURL     = NULL;
    PCHAR                           pTempString     = NULL;
    PHTTP_AUTH_CLIENT_OBJECT        pAuthClientObj  = NULL;
    char                            pNewUrl[257]    = { 0 };
    ULONG                           uRedirect       = 0;
    ULONG                           uMaxRedirect    = 5;
	ULONG							ulRpcCallTimeout= CCSP_CWMPSO_RPCCALL_TIMEOUT; 

    /* If the response is 401 authentication required, we need to try again */
    int                             nMaxAuthRetries = 2;

    if( pMyObject->AcsUrl == NULL || AnscSizeOfString(pMyObject->AcsUrl) <= 10 || pHttpHfpIf == NULL)
    {
        return ANSC_STATUS_NOT_READY;
    }

    AnscZeroMemory(pHttpGetReq, sizeof(ANSC_ACS_INTERN_HTTP_CONTENT));

    CcspTr069PaTraceDebug(("CcspCwmpAcscoRequest -- AcsUrl = '%s'\n", pMyObject->AcsUrl));

    pHttpCasIf  = (PHTTP_CAS_INTERFACE)pHttpClient->GetCasIf((ANSC_HANDLE)pHttpClient);

    if ( pHttpCasIf != NULL)
    {
        if( pMyObject->Username == NULL || AnscSizeOfString(pMyObject->Username) == 0)
        {
            pHttpCasIf->EnableAuth(pHttpCasIf->hOwnerContext, FALSE);
        }
        else
        {
            pHttpCasIf->EnableAuth(pHttpCasIf->hOwnerContext, TRUE);

            pAuthClientObj  = (PHTTP_AUTH_CLIENT_OBJECT)pHttpClient->GetClientAuthObj((ANSC_HANDLE)pHttpClient);

            if ( pAuthClientObj != NULL)
            {
                pAuthClientObj->SetAcmIf((ANSC_HANDLE)pAuthClientObj, (ANSC_HANDLE)pMyObject->hHttpAcmIf);
            }
            else
            {
                CcspTr069PaTraceError(("Failed to Get HttpAuthClient object.\n"));
            }
        }
    }

#ifdef   _DEBUG
    if ( !pSoapMessage )
    {
        CcspTr069PaTraceDebug(("CPE Request:\n<EMPTY>\n"));
    }
    else if ( AnscSizeOfString(pSoapMessage) <= CCSP_CWMP_TRACE_MAX_SOAP_MSG_LENGTH )
    {
        CcspTr069PaTraceDebug(("CPE Request:\n%s\n", pSoapMessage));
    }
    else
    {
        char                        partSoap[CCSP_CWMP_TRACE_MAX_SOAP_MSG_LENGTH+1+8];

        AnscCopyMemory(partSoap, pSoapMessage, CCSP_CWMP_TRACE_MAX_SOAP_MSG_LENGTH);
        partSoap[CCSP_CWMP_TRACE_MAX_SOAP_MSG_LENGTH] = '\n';
        partSoap[CCSP_CWMP_TRACE_MAX_SOAP_MSG_LENGTH+1] = '.';
        partSoap[CCSP_CWMP_TRACE_MAX_SOAP_MSG_LENGTH+2] = '.';
        partSoap[CCSP_CWMP_TRACE_MAX_SOAP_MSG_LENGTH+3] = '.';
        partSoap[CCSP_CWMP_TRACE_MAX_SOAP_MSG_LENGTH+4] = '\n';
        partSoap[CCSP_CWMP_TRACE_MAX_SOAP_MSG_LENGTH+5] = 0;
        CcspTr069PaTraceDebug(("CPE Request:\n%s\n", partSoap));
    }
#endif
    
START:
    pRequestURL = pMyObject->AcsUrl;

    pHttpReqInfo =
        (PHTTP_REQUEST_URI)pHttpHfpIf->ParseHttpUrl
            (
                pHttpHfpIf->hOwnerContext,
                pRequestURL,
                AnscSizeOfString(pRequestURL)
            );

    if ( !pHttpReqInfo )
    {
        return ANSC_STATUS_INTERNAL_ERROR;
    }

    pHttpReqInfo->Type = HTTP_URI_TYPE_ABS_PATH;

    /* init the request */
    AnscZeroMemory(pHttpGetReq, sizeof(ANSC_ACS_INTERN_HTTP_CONTENT));
    pHttpGetReq->bIsRedirect    = FALSE;
    pHttpGetReq->SoapMessage    = pSoapMessage;

    /* When there is more than one envelope in a single HTTP Request,
     * when there is a SOAP response in an HTTP Request, or when there is a
     * SOAP Fault response in an HTTP Request, the SOAPAction header in the
     * HTTP Request MUST have no value (with no quotes), indicating that this
     * header provides no information as to the intent of the message."
     */
    if( ulReqEnvCount == 1 && ulRepEnvCount == 0)
    {
        pHttpGetReq->MethodName     = pMethodName;
    }

    AnscInitializeEvent(&pHttpGetReq->CompleteEvent);

    while ( nMaxAuthRetries > 0 )
    {
        CcspTr069PaTraceInfo(("ACS Request now at: %u\n", (unsigned int)AnscGetTickInSeconds()));

        if ( AnscEqualString2(pRequestURL, "https", 5, FALSE) )
        {
            bApplyTls = TRUE;
        }
        else if ( AnscEqualString2(pRequestURL, "http", 4, FALSE) )
        {
            if ( bIsComcastImage() ){                
#ifdef _SUPPORT_HTTP
               CcspTr069PaTraceInfo(("HTTP request from ACS is supported\n"));
               bApplyTls = FALSE;
#else
               CcspTr069PaTraceInfo(("TR-069 blocked unsecured traffic from ACS\n"));
               pHttpGetReq->CompleteStatus = ANSC_STATUS_NOT_SUPPORTED;
               pHttpGetReq->bUnauthorized = TRUE;
               pHttpGetReq->bIsRedirect = FALSE;
               break;
#endif
            }
            else {
               bApplyTls = FALSE; 
            }
        }
        else
        {
             pHttpGetReq->CompleteStatus = ANSC_STATUS_NOT_SUPPORTED;
             pHttpGetReq->bUnauthorized = FALSE;
             pHttpGetReq->bIsRedirect = FALSE;
             break;
        }

        if(pHttpGetReq->pContent != NULL)
        {
            CcspTr069PaFreeMemory(pHttpGetReq->pContent);

            pHttpGetReq->pContent = NULL;
        }

        pHttpGetReq->CompleteStatus = ANSC_STATUS_FAILURE;
        pHttpGetReq->bUnauthorized  = FALSE;
        AnscResetEvent     (&pHttpGetReq->CompleteEvent);

        returnStatus =
            pHttpClient->Request
                (
                    (ANSC_HANDLE)pHttpClient,
                    (ULONG      )HTTP_METHOD_CODE_POST,
                    (ANSC_HANDLE)pHttpReqInfo,
                    (ANSC_HANDLE)pHttpGetReq,
                    bApplyTls
                );

        if( returnStatus != ANSC_STATUS_SUCCESS)
        {
            CcspTr069PaTraceError(("ACS Request failed: returnStatus = %.X\n", (unsigned int)returnStatus));
			break;
        }

		if ( pCcspCwmpCfgIf && pCcspCwmpCfgIf->GetCwmpRpcTimeout )
		{
			ulRpcCallTimeout = pCcspCwmpCfgIf->GetCwmpRpcTimeout(pCcspCwmpCfgIf->hOwnerContext);	
			if ( ulRpcCallTimeout < CCSP_CWMPSO_RPCCALL_TIMEOUT )
			{
				ulRpcCallTimeout = CCSP_CWMPSO_RPCCALL_TIMEOUT;
			}
		}

        AnscWaitEvent(&pHttpGetReq->CompleteEvent, ulRpcCallTimeout * 1000);
        if ( pHttpGetReq->CompleteStatus == ANSC_STATUS_SUCCESS && pHttpGetReq->bUnauthorized && nMaxAuthRetries > 0 )
        {
            CcspTr069PaTraceError(("ACS Request is not authenticated, try again.\n"));
            nMaxAuthRetries --;
			
#ifdef _ANSC_USE_OPENSSL_
            if( bApplyTls )
        	{
	        	if ( ANSC_STATUS_SUCCESS == CcspTr069PaSsp_GetTr069CertificateLocationForSyndication( &openssl_client_ca_certificate_files ) )
        		{
					openssl_load_ca_certificates( SSL_CLIENT_CALLS );
        		}
        	}
#endif /* _ANSC_USE_OPENSSL_ */
        }
        else
        {
            CcspTr069PaTraceInfo(("ACS Request has completed with status code %lu, at %lu\n", pHttpGetReq->CompleteStatus, AnscGetTickInSeconds()));

            break;
        }
    }

    /* AnscResetEvent (&pHttpGetReq->CompleteEvent); */
    AnscFreeEvent(&pHttpGetReq->CompleteEvent);

    CcspTr069PaFreeMemory(pHttpReqInfo);

    if ( pHttpGetReq->CompleteStatus != ANSC_STATUS_SUCCESS )
    {
        if ( pHttpGetReq->CompleteStatus == ANSC_STATUS_RESET_SESSION )
        {
            goto  REDIRECTED;
        }
        else
        {
            returnStatus = pHttpGetReq->CompleteStatus;

            goto  EXIT;
        }
    }
    else if( pHttpGetReq->bUnauthorized)
    {
        returnStatus = ANSC_STATUS_FAILURE;

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

        goto EXIT;
    }

REDIRECTED:
    if( pHttpGetReq->bIsRedirect)
    {
        if( _ansc_strstr((PCHAR)pHttpGetReq->pContent, "http") == pHttpGetReq->pContent)
        {
            if ( pMyObject->AcsUrl ) CcspTr069PaFreeMemory(pMyObject->AcsUrl);
            pMyObject->AcsUrl = CcspTr069PaCloneString(pHttpGetReq->pContent);
        }
        else
        {
            /* if it's partial path */
            pTempString = _ansc_strstr(pRequestURL, "//");

            if( pTempString == NULL)
            {
                returnStatus = ANSC_STATUS_FAILURE;

                goto EXIT;
            }

            pTempString += AnscSizeOfString("//");
            pTempString  = _ansc_strstr(pTempString, "/");

            if( pTempString == NULL)
            {
                returnStatus = ANSC_STATUS_FAILURE;

                goto EXIT;
            }

            AnscCopyMemory(pNewUrl, pRequestURL, (ULONG)(pTempString - pRequestURL));
            AnscCatString(pNewUrl, (PCHAR)pHttpGetReq->pContent);

            if ( pMyObject->AcsUrl ) CcspTr069PaFreeMemory(pMyObject->AcsUrl);
            pMyObject->AcsUrl = CcspTr069PaCloneString(pNewUrl);
        }

        uRedirect ++;

        if( uRedirect >= uMaxRedirect)
        {
            CcspTr069PaTraceDebug(("Maximum Redirection reached. Give up!\n"));

            returnStatus = ANSC_STATUS_FAILURE;

            goto EXIT;
        }
        else
        {
            CcspTr069PaTraceDebug(("Acs connection redirection #%u: '%s'\n", (unsigned int)uRedirect, pMyObject->AcsUrl));

            /* in case redirected ACS challenges CPE again */
            nMaxAuthRetries = 2;

            /* tear down current HTTP session before redirecting to new ACS,
             * otherwise, there might be case that ACS sends out redirection
             * response and immediately closes the socket, CWMP may be 
             * confused by closing CWMP session prematurely. 
             */
            pHttpClient->DelAllWcsos((ANSC_HANDLE)pHttpClient);

            goto START;
        }
    }

    if(pWmpSession != NULL)
    {
        if( pHttpGetReq->ulContentSize > 0 && pHttpGetReq->pContent != NULL)
        {
            CcspTr069PaTraceDebug(("Response:\n%s\n", (char*)pHttpGetReq->pContent));

            returnStatus =
                pWmpSession->RecvSoapMessage
                    (
                       pWmpSession,
                       (PCHAR)pHttpGetReq->pContent
                    );
        }
        else
        {
            CcspTr069PaTraceDebug(("Response: <EMPTY>\n"));

            returnStatus =
                pCcspCwmpMcoIf->NotifyAcsStatus
                    (
                        pCcspCwmpMcoIf->hOwnerContext,
                        TRUE,           /* no more requests */
                        FALSE
                    );
        }
    }

EXIT:

    if(pHttpGetReq->pContent != NULL)
    {
        CcspTr069PaFreeMemory(pHttpGetReq->pContent);

        pHttpGetReq->pContent = NULL;
    }

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

    return returnStatus;
}