ANSC_STATUS
BbhmUdpechoCancel
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS            returnStatus = ANSC_STATUS_SUCCESS;
    PBBHM_UDP_ECHOSRV_OBJECT  pMyObject = (PBBHM_UDP_ECHOSRV_OBJECT)hThisObject;
    ULONG                           i                  = 0;

    pMyObject->StopDiag(pMyObject);

    /* wait until the server is stop successfully */
    while( pMyObject->bIsServerOn && i < 300)
    {
        AnscSleep(500);

        i ++;
    }

    if ( !pMyObject->bActive )
    {
        return  ANSC_STATUS_SUCCESS;
    }

    pMyObject->bActive = FALSE;

    return  returnStatus;
}
ANSC_STATUS
AnscLpccoTcpBwoRemove
    (
        ANSC_HANDLE                 hThisObject,
        ANSC_HANDLE                 hSocket
    )
{
    ANSC_STATUS                     returnStatus  = ANSC_STATUS_SUCCESS;
    PANSC_LPCCO_TCP_OBJECT          pMyObject     = (PANSC_LPCCO_TCP_OBJECT        )hThisObject;
    PANSC_DAEMON_SERVER_TCP_OBJECT  pDaemonServer = (PANSC_DAEMON_SERVER_TCP_OBJECT)pMyObject->hDaemonServer;
    PANSC_BROKER_SERVER_TCP_OBJECT  pBrokerServer = (PANSC_BROKER_SERVER_TCP_OBJECT)pMyObject->hBrokerServer;
    PANSC_TIMER_DESCRIPTOR_OBJECT   pConnTimerObj = (PANSC_TIMER_DESCRIPTOR_OBJECT )pMyObject->hConnTimerObj;
    PANSC_BROKER_SOCKET_TCP_OBJECT  pBrokerSocket = (PANSC_BROKER_SOCKET_TCP_OBJECT)hSocket;
    PANSC_BUFFER_DESCRIPTOR         pBufferDesp   = (PANSC_BUFFER_DESCRIPTOR       )pBrokerSocket->GetBufferContext((ANSC_HANDLE)pBrokerSocket);
    PANSC_LPC_PARTY_ADDR            pPartyAddr    = (PANSC_LPC_PARTY_ADDR          )pBrokerSocket->GetClientContext((ANSC_HANDLE)pBrokerSocket);

    pBrokerSocket->SetClientContext((ANSC_HANDLE)pBrokerSocket, (ANSC_HANDLE)NULL         );
    pBrokerSocket->SetBufferContext((ANSC_HANDLE)pBrokerSocket, NULL, 0, (ANSC_HANDLE)NULL);

    if ( pBufferDesp )
    {
        AnscFreeBdo((ANSC_HANDLE)pBufferDesp);
    }

    if ( pPartyAddr )
    {
        pPartyAddr->Timestamp   = AnscGetTickInSeconds();
        pPartyAddr->PartyState &= ~ANSC_LPC_PARTY_STATE_connectedOut;
        pPartyAddr->PartySocket = (ANSC_HANDLE)NULL;

        /*
         * We shouldn't return until the reference count of 'pPartyAddr' reaches zero. Because if
         * we do, the socket may be deleted while there's still active task is trying to send
         * message to this party. For example: if LPC manager is issuing a LOCO call to all LPC
         * parties while one party is trying disconnect, a race condition is formed.
         */
        while ( pPartyAddr->ActiveCalls > 0 )
        {
            AnscSleep(20);
        }

        if ( !(pPartyAddr->PartyState & ANSC_LPC_PARTY_STATE_connectedIn ) &&
             !(pPartyAddr->PartyState & ANSC_LPC_PARTY_STATE_connectedOut) )
        {
            if ( pMyObject->bActive )
            {
                pConnTimerObj->Stop       ((ANSC_HANDLE)pConnTimerObj);
                pConnTimerObj->SetInterval((ANSC_HANDLE)pConnTimerObj, ANSC_LPCCO_DEF_CONN_TIMEOUT);
                pConnTimerObj->Start      ((ANSC_HANDLE)pConnTimerObj);
            }
        }
    }

    return  ANSC_STATUS_SUCCESS;
}
ANSC_STATUS
CcspCwmpsoCloseConnection
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus       = ANSC_STATUS_SUCCESS;
    PCCSP_CWMP_SESSION_OBJECT       pMyObject          = (PCCSP_CWMP_SESSION_OBJECT     )hThisObject;
    PANSC_TIMER_DESCRIPTOR_OBJECT   pSessionTimerObj   = (PANSC_TIMER_DESCRIPTOR_OBJECT)pMyObject->hSessionTimerObj;
    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;
    PCCSP_CWMP_MPA_INTERFACE        pCcspCwmpMpaIf         = (PCCSP_CWMP_MPA_INTERFACE          )pCcspCwmpProcessor->GetCcspCwmpMpaIf((ANSC_HANDLE)pCcspCwmpProcessor);
    int                             DelayTimes        = 10; 

    pSessionTimerObj->Stop((ANSC_HANDLE)pSessionTimerObj);

    pMyObject->bActive      = FALSE;
    pMyObject->SessionState = CCSP_CWMPSO_SESSION_STATE_idle;

    /* would cause crash if AsyncProcessEvent is freed asynchronously */
    /*
    CcspTr069PaTraceDebug(("CcspCwmpsoCloseConnection -> SetEvent\n"));
    AnscSetEvent(&pMyObject->AsyncProcessEvent);
    */
    CcspTr069PaTraceDebug(("CcspCwmpsoCloseConnection -> waiting for all tasks exit ...\n"));

    while ( pMyObject->AsyncTaskCount > 0 && DelayTimes > 0 )
    {
        AnscSleep(500);
        DelayTimes --;
    }

    CcspTr069PaTraceDebug(("CcspCwmpsoCloseConnection -> Close\n"));
    pCcspCwmpAcsConnection->Close((ANSC_HANDLE)pCcspCwmpAcsConnection);

    CcspTr069PaTraceDebug(("CcspCwmpsoCloseConnection -> UnlockWriteAccess\n"));
    pCcspCwmpMpaIf->UnlockWriteAccess(pCcspCwmpMpaIf->hOwnerContext);

    return  ANSC_STATUS_SUCCESS;
}
ANSC_STATUS
StunScoCancel
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus      = ANSC_STATUS_SUCCESS;
    PSTUN_SIMPLE_CLIENT_OBJECT      pMyObject         = (PSTUN_SIMPLE_CLIENT_OBJECT    )hThisObject;
    PSTUN_SIMPLE_CLIENT_PROPERTY    pProperty         = (PSTUN_SIMPLE_CLIENT_PROPERTY  )&pMyObject->Property;
    PANSC_TIMER_DESCRIPTOR_OBJECT   pStageTimerObj    = (PANSC_TIMER_DESCRIPTOR_OBJECT )pMyObject->hStageTimerObj;
    PANSC_TIMER_DESCRIPTOR_OBJECT   pRetryTimerObj    = (PANSC_TIMER_DESCRIPTOR_OBJECT )pMyObject->hRetryTimerObj;
    PANSC_TIMER_DESCRIPTOR_OBJECT   pProbeTimerObj    = (PANSC_TIMER_DESCRIPTOR_OBJECT )pMyObject->hProbeTimerObj;
    PANSC_SIMPLE_CLIENT_UDP_OBJECT  pSimpleClientUdp1 = (PANSC_SIMPLE_CLIENT_UDP_OBJECT)pMyObject->hSimpleClientUdp1;

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

    while ( pMyObject->AsyncTaskCount > 0 )
    {
        AnscSetEvent(&pMyObject->SocketEventA);
        AnscSleep(1000);
    }

    pStageTimerObj->Stop((ANSC_HANDLE)pStageTimerObj);
    pRetryTimerObj->Stop((ANSC_HANDLE)pRetryTimerObj);
    pProbeTimerObj->Stop((ANSC_HANDLE)pProbeTimerObj);

    pSimpleClientUdp1->Cancel((ANSC_HANDLE)pSimpleClientUdp1);

    pMyObject->Reset((ANSC_HANDLE)pMyObject);

    return  returnStatus;
}
ANSC_STATUS
AnscSctoCancel
    (
        ANSC_HANDLE                 hThisObject
    )
{
    PANSC_SIMPLE_CLIENT_TCP_OBJECT  pMyObject    = (PANSC_SIMPLE_CLIENT_TCP_OBJECT)hThisObject;

    if ( !pMyObject->bActive )
    {
        return  ANSC_STATUS_SUCCESS;
    }
    else
    {
    	pMyObject->bShuttingDown = TRUE;
        pMyObject->bActive = FALSE;
        pMyObject->bClosed = TRUE;

        while ( pMyObject->EngineTaskCount != 0 )
        {
            AnscSleep(500);
        }

    }

#ifdef _ANSC_USE_OPENSSL_
    if ( pMyObject->hTlsConnection )
    {
        SSL *ssl = (SSL *) pMyObject->hTlsConnection;
    	AnscTrace ("SSL connection %p is closed.\n", ssl);
        SSL_shutdown (ssl);
        SSL_free (ssl);
    }
#else
    if ( pMyObject->bTlsEnabled && pMyObject->hTlsScsIf )
    {
        PTLS_SCS_INTERFACE              pTlsScsIf    = (PTLS_SCS_INTERFACE            )pMyObject->hTlsScsIf;

        AnscSetEvent(&pMyObject->TlsConnEvent);

        if ( pMyObject->hTlsConnection )
        {
            if ( pMyObject->bTlsConnected )
            {
                    pTlsScsIf->CloseConnection
                        (
                            pTlsScsIf->hOwnerContext,
                            pMyObject->hTlsConnection
                        );
            }

                pTlsScsIf->RemoveConnection
                    (
                        pTlsScsIf->hOwnerContext,
                        pMyObject->hTlsConnection
                    );
        }

        pMyObject->bTlsConnected = FALSE;
    }
#endif

    if ( pMyObject->Mode & ANSC_SCTO_MODE_XSOCKET )
    {
        if ( (XSKT_SOCKET)pMyObject->Socket != XSKT_SOCKET_INVALID_SOCKET )
        {
            _xskt_shutdown   (((XSKT_SOCKET)pMyObject->Socket), XSKT_SOCKET_SD_RECV);
            _xskt_closesocket(((XSKT_SOCKET)pMyObject->Socket));

            pMyObject->Socket = (ANSC_SOCKET)XSKT_SOCKET_INVALID_SOCKET;
        }
    }
    else
    {
        if ( pMyObject->Socket != ANSC_SOCKET_INVALID_SOCKET )
        {
            _ansc_shutdown   (pMyObject->Socket, ANSC_SOCKET_SD_RECV);
            _ansc_closesocket(pMyObject->Socket);

            pMyObject->Socket = ANSC_SOCKET_INVALID_SOCKET;
        }
    }

    /*
     * The underlying socket wrapper may require an explicit cleanup() call, such is the case on
     * Microsoft windows platforms. The wrapper initialization has to done for each task. On most
     * real-time operating systems, this call is not required.
     */
    if ( pMyObject->Mode & ANSC_SCTO_MODE_XSOCKET )
    {
        AnscCleanupXsocketWrapper((ANSC_HANDLE)pMyObject);
    }
    else
    {
        AnscCleanupSocketWrapper((ANSC_HANDLE)pMyObject);
    }

    pMyObject->Reset((ANSC_HANDLE)pMyObject);

    return  ANSC_STATUS_SUCCESS;
}
ANSC_STATUS
AnscSctoEngage
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    PANSC_SIMPLE_CLIENT_TCP_OBJECT  pMyObject    = (PANSC_SIMPLE_CLIENT_TCP_OBJECT)hThisObject;
    PANSC_SCTO_WORKER_OBJECT        pWorker      = (PANSC_SCTO_WORKER_OBJECT      )pMyObject->hWorker;
    int                             s_error      = 0;
    ansc_socket_addr_in             ansc_client_addr;
    ansc_socket_addr_in             ansc_server_addr;
    xskt_socket_addr_in             xskt_client_addr;
    xskt_socket_addr_in             xskt_server_addr;

#ifdef _ANSC_IPV6_COMPATIBLE_
    ansc_addrinfo                   ansc_hints            = {0};
    ansc_addrinfo*                  pansc_server_addrinfo = NULL;
    ansc_addrinfo*                  pansc_client_addrinfo = NULL;
    xskt_addrinfo                   xskt_hints            = {0};
    xskt_addrinfo*                  pxskt_server_addrinfo = NULL;
    xskt_addrinfo*                  pxskt_client_addrinfo = NULL;
    USHORT                          usPort                = 0;
    char                            port[6] = {0};
#endif

    if ( pMyObject->bActive )
    {
        return  ANSC_STATUS_SUCCESS;
    }
    else if ( !pWorker )
    {
        return  ANSC_STATUS_UNAPPLICABLE;
    }
    else
    {
        /*
         * Just like any other socket-based ANSC object, we will create a separate async recv task
         * which is dedicated to receiving packets. This async recv task is controlled by 'bActive'
         * flag. What if at this moment right before we're about to enable the socket operation and
         * setting 'bActive' flag to TRUE, the old recv task created by the last call of Engage()
         * is still running? While it may not cause crash, but it certainly confuses the owner
         * object because all async recv tasks share the same worker interface. The most obvious
         * solution is to wait for previous recv task to exit before creating a new one.
         */
    	while ( pMyObject->EngineTaskCount != 0 )
        {
            AnscSleep(50);
        }

        pMyObject->bActive = TRUE;
        pMyObject->bClosed = FALSE;
    }

    /*
     * The underlying socket wrapper may require an explicit startup() call, such is the case on
     * Microsoft windows platforms. The wrapper initialization has to done for each task. On most
     * real-time operating systems, this call is not required.
     */
    if ( pMyObject->Mode & ANSC_SCTO_MODE_XSOCKET )
    {
        AnscStartupXsocketWrapper((ANSC_HANDLE)pMyObject);
    }
    else
    {
        AnscStartupSocketWrapper((ANSC_HANDLE)pMyObject);
    }

    #ifdef _ANSC_IPV6_COMPATIBLE_

    if ( pMyObject->Mode & ANSC_SCTO_MODE_XSOCKET )
    {
        xskt_hints.ai_family   = AF_UNSPEC;
        xskt_hints.ai_socktype = XSKT_SOCKET_STREAM;
        xskt_hints.ai_flags    = AI_CANONNAME;

        usPort = pMyObject->GetPeerPort((ANSC_HANDLE)pMyObject);
        _ansc_sprintf(port, "%d", usPort);

        AnscTrace("!!! Peer Port: %s !!!\n", port);

        char * pPeerName = pMyObject->GetPeerName((ANSC_HANDLE)pMyObject);

        AnscTrace("Peer Name: %s!!!\n", pPeerName);

/*
        struct addrinfo hints,*res=NULL;
	memset(&hints,0,sizeof(hints));
	hints.ai_family=PF_UNSPEC;
	hints.ai_socktype=SOCK_DGRAM;
	hints.ai_protocol=IPPROTO_UDP;
	s_error=getaddrinfo("127.0.0.1","123",&hints,&res);
*/
/*
         s_error = _xskt_getaddrinfo
                (
                    "10.74.52.92",
                    port,
                    &xskt_hints,
                    &pxskt_server_addrinfo
                );

        AnscTrace("!!!!!! _xskt_getaddrinfo returns: %d %s !!!\n", s_error, gai_strerror(s_error));
*/
        if ( _xskt_getaddrinfo
                (
                    pMyObject->GetPeerName((ANSC_HANDLE)pMyObject), 
                    port,
                    &xskt_hints,
                    &pxskt_server_addrinfo
                ) ||
             _xskt_getaddrinfo
                (
                    "localhost", 
                    NULL,
                    &xskt_hints,
                    &pxskt_client_addrinfo
                )

            )
        {
            AnscTrace("!!! error 1 !!!\n");

            if ( pMyObject->Mode & ANSC_SCTO_MODE_NO_BSP_NOTIFY_CONN_ERR == 0 )
            {
                pWorker->Notify
	            	(
            		    pWorker->hWorkerContext,
            		    ANSC_SCTOWO_EVENT_SOCKET_ERROR,
            		    (ANSC_HANDLE)NULL
            		);
            }

            returnStatus = ANSC_STATUS_FAILURE;

            goto  EXIT1;
        }

        AnscTrace("!!! after getaddrinfo !!!\n");
    }
    else
    {
        ansc_hints.ai_family   = AF_UNSPEC;
        ansc_hints.ai_socktype = ANSC_SOCKET_STREAM;
        ansc_hints.ai_flags    = AI_CANONNAME;

        usPort = pMyObject->GetPeerPort((ANSC_HANDLE)pMyObject);
        _ansc_sprintf(port, "%d", usPort);

        if ( _ansc_getaddrinfo
                (
                    pMyObject->GetPeerName((ANSC_HANDLE)pMyObject), 
                    port,
                    &ansc_hints,
                    &pansc_server_addrinfo
                ) ||
             _ansc_getaddrinfo
                (
                    "localhost", 
                    NULL,
                    &ansc_hints,
                    &pansc_client_addrinfo
                )
            )
        {
            if ( pMyObject->Mode & ANSC_SCTO_MODE_NO_BSP_NOTIFY_CONN_ERR == 0 )
            {
                pWorker->Notify
	            	(
            		    pWorker->hWorkerContext,
		                ANSC_SCTOWO_EVENT_SOCKET_ERROR,
            	        (ANSC_HANDLE)NULL
	                );
            }

            returnStatus = ANSC_STATUS_FAILURE;

            goto  EXIT1;
        }
    }

#endif

    /*
     * To engage the Tcp Client, we need to perform following acts in the respective order:
     *
     *      (1) create the os-dependent socket
     *      (2) bind to the newly socket
     *      (3) connect to the specified  server address
     *      (4) allocate a buffer for receiving
     *      (5) spawn a separate thread and start receiving
     */
    if ( pMyObject->Mode & ANSC_SCTO_MODE_XSOCKET )
    {
#ifdef _ANSC_IPV6_COMPATIBLE_
        pMyObject->Socket = (ANSC_SOCKET)_xskt_socket(pxskt_server_addrinfo->ai_family, pxskt_server_addrinfo->ai_socktype, 0);
#else
        pMyObject->Socket = (ANSC_SOCKET)_xskt_socket(XSKT_SOCKET_AF_INET, XSKT_SOCKET_STREAM, 0);
#endif

        if ( (XSKT_SOCKET)pMyObject->Socket == XSKT_SOCKET_INVALID_SOCKET )
        {
            AnscTrace("!!!!!!!!!! _xskt_socket error !!!!!!!!!!\n");
            if ( pMyObject->Mode & ANSC_SCTO_MODE_NO_BSP_NOTIFY_CONN_ERR == 0 )
            {
                pWorker->Notify
	    			(
		    			pWorker->hWorkerContext,
			    		ANSC_SCTOWO_EVENT_SOCKET_ERROR,
				    	(ANSC_HANDLE)NULL
    				);
            }

            returnStatus = ANSC_STATUS_FAILURE;

            goto  EXIT1;
        }
        else  AnscTrace("Opening IPv4 socket Ok\n");
    }
    else
    {
#ifdef _ANSC_IPV6_COMPATIBLE_
        pMyObject->Socket = _ansc_socket(pansc_server_addrinfo->ai_family, pansc_server_addrinfo->ai_socktype, 0);
#else
        pMyObject->Socket = _ansc_socket(ANSC_SOCKET_AF_INET, ANSC_SOCKET_STREAM, 0);
#endif

        if ( pMyObject->Socket == ANSC_SOCKET_INVALID_SOCKET )
        {
            if ( pMyObject->Mode & ANSC_SCTO_MODE_NO_BSP_NOTIFY_CONN_ERR == 0 )
            {
                pWorker->Notify
	    			(
		    			pWorker->hWorkerContext,
			    		ANSC_SCTOWO_EVENT_SOCKET_ERROR,
				    	(ANSC_HANDLE)NULL
    				);
            }

            returnStatus = ANSC_STATUS_FAILURE;

            goto  EXIT1;
        }
    }
    /*
     * Normally we don't need to know which local network interface we shall bind to, and the
     * underlying operating system usually supports such notation as "any address".
     */
#ifndef _ANSC_IPV6_COMPATIBLE_
    if ( pMyObject->Mode & ANSC_SCTO_MODE_XSOCKET )
    {
        xskt_client_addr.sin_family = XSKT_SOCKET_AF_INET;
        xskt_client_addr.sin_port   = _xskt_htons(pMyObject->HostPort);

        if (pMyObject->bSocketBindToDevice && *(pMyObject->SocketDeviceName)) 
        {
            if (_xskt_setsocketopt
                    (
                         pMyObject->Socket, 
                         XSKT_SOCKET_SOL_SOCKET, 
                         XSKT_SOCKET_SO_BINDTODEVICE, 
                         pMyObject->SocketDeviceName, 
                         _ansc_strlen(pMyObject->SocketDeviceName) + 1
                    )
                < 0)
            {
                perror("setsockopt-SOL_SOCKET-SO_BINDTODEVICE");
                returnStatus = ANSC_STATUS_FAILURE;
                goto EXIT2;
            }
        }
        //        fprintf(stderr, "<RT XSKT> Binding socket to Device '%s'.\n", pMyObject->SocketDeviceName); 

        if ( pMyObject->HostAddress.Value == 0 )
        {
            ((pansc_socket_addr_in)&xskt_client_addr)->sin_addr.s_addr = XSKT_SOCKET_ANY_ADDRESS;
        }
        else
        {
            ((pansc_socket_addr_in)&xskt_client_addr)->sin_addr.s_addr = pMyObject->HostAddress.Value;
        }

        if ( _xskt_bind((XSKT_SOCKET)pMyObject->Socket, (xskt_socket_addr*)&xskt_client_addr, sizeof(xskt_client_addr)) != 0 )
        {
            AnscTrace("!!!!!!!!!! _xskt_bind error: socket=%d, error=%d !!!!!!!!!!\n", (XSKT_SOCKET)pMyObject->Socket, errno);
            {
                int j;                 
                char s[256];
                char *ptr1 = ((xskt_socket_addr*)(&xskt_client_addr))->sa_data;
                char stmp[16];

                s[0] = '\0';                  
                for(j=0; j<13; j++) {
                    sprintf(stmp, "%.2x:", *(ptr1++));
                    strcat(s, stmp);
                }
                sprintf(stmp, "%.2x", *ptr1); 
                strcat(s, stmp);
                AnscTrace("!!!!!!!!!! _xskt_bind error: client_addr=%s\n", s);
            }
            perror("_xskt_bind error");

            if ( pMyObject->Mode & ANSC_SCTO_MODE_NO_BSP_NOTIFY_CONN_ERR == 0 )
            {
                pWorker->Notify
	    			(
		    			pWorker->hWorkerContext,
			    		ANSC_SCTOWO_EVENT_SOCKET_ERROR,
				    	(ANSC_HANDLE)NULL
    				);
            }
            returnStatus = ANSC_STATUS_FAILURE;

            goto  EXIT2;
        }
    }
    else
    {
        ansc_client_addr.sin_family = ANSC_SOCKET_AF_INET;
        ansc_client_addr.sin_port   = _ansc_htons(pMyObject->HostPort);

        if (pMyObject->bSocketBindToDevice && *(pMyObject->SocketDeviceName)) 
        {
            if (_xskt_setsocketopt
                    (
                         pMyObject->Socket, 
                         ANSC_SOCKET_SOL_SOCKET, 
                         ANSC_SOCKET_SO_BINDTODEVICE, 
                         pMyObject->SocketDeviceName, 
                         _ansc_strlen(pMyObject->SocketDeviceName) + 1
                    )
                < 0)
            {
                perror("setsockopt-SOL_SOCKET-SO_BINDTODEVICE");
                returnStatus = ANSC_STATUS_FAILURE;
                goto EXIT2;
            }
        }
        // fprintf(stderr, "<RT AnscSKT> Binding socket to Device '%s'.\n", pMyObject->SocketDeviceName); 


        if ( pMyObject->HostAddress.Value == 0 )
        {
            ansc_client_addr.sin_addr.s_addr = ANSC_SOCKET_ANY_ADDRESS;
        }
        else
        {
            ansc_client_addr.sin_addr.s_addr = pMyObject->HostAddress.Value;
        }

        if ( _ansc_bind(pMyObject->Socket, (ansc_socket_addr*)&ansc_client_addr, sizeof(ansc_client_addr)) != 0 )
        {
            AnscTrace("!!!!!!!!!! _ansc_bind error: socket=%d, error=%d !!!!!!!!!!\n", (XSKT_SOCKET)pMyObject->Socket, errno);
            {
                int j;                 
                char s[256];
                char *ptr1 = ((ansc_socket_addr*)(&ansc_client_addr))->sa_data;
                char stmp[16];

                s[0] = '\0';                  
                for(j=0; j<13; j++) {
                    sprintf(stmp, "%.2x:", *(ptr1++));
                    strcat(s, stmp);
                }
                sprintf(stmp, "%.2x", *ptr1); 
                strcat(s, stmp);
                AnscTrace("!!!!!!!!!! _ansc_bind error: client_addr=%s\n", s);
            }
            perror("_ansc_bind error");

            if ( pMyObject->Mode & ANSC_SCTO_MODE_NO_BSP_NOTIFY_CONN_ERR == 0 )
            {
                pWorker->Notify
	    			(
		    			pWorker->hWorkerContext,
			    		ANSC_SCTOWO_EVENT_SOCKET_ERROR,
				    	(ANSC_HANDLE)NULL
    				);
            }

            returnStatus = ANSC_STATUS_FAILURE;

            goto  EXIT2;
        }
    }
#endif

    /*
     * As a Tcp client application, we now try to connect the network server, whose address is
     * specified by the "peer address" and "peer port" fields.
     */
    if ( pMyObject->Mode & ANSC_SCTO_MODE_XSOCKET )
    {
#ifdef _ANSC_IPV6_COMPATIBLE_
        BOOL                        bNoConn = TRUE;
#endif

        _ansc_memset(&xskt_server_addr, 0, sizeof(xskt_server_addr));
    	xskt_server_addr.sin_family                                 = XSKT_SOCKET_AF_INET;
        xskt_server_addr.sin_addr.s_addr  = pMyObject->PeerAddress.Value;
        xskt_server_addr.sin_port                                   = _xskt_htons(pMyObject->PeerPort);

#ifdef _ANSC_IPV6_COMPATIBLE_
        while ( bNoConn && pxskt_server_addrinfo )
        {
            if ( _xskt_connect((XSKT_SOCKET)pMyObject->Socket, pxskt_server_addrinfo->ai_addr, pxskt_server_addrinfo->ai_addrlen) != 0 )
            {
                pxskt_server_addrinfo = pxskt_server_addrinfo->ai_next;     /* try next ip address */
            }
            else
            {
                bNoConn = FALSE;
                break;
            }
        }

        if ( bNoConn )
#else
            if ( _xskt_connect((XSKT_SOCKET)pMyObject->Socket, (xskt_socket_addr*)&xskt_server_addr, sizeof(xskt_server_addr)) != 0 )
#endif
        {
            AnscTrace("!!!!!!!!!! _xskt_connect error: socket=%d, error=%d !!!!!!!!!!\n", (XSKT_SOCKET)pMyObject->Socket, errno);
            {
                int j;                 
                char s[256];
                char *ptr1 = ((xskt_socket_addr*)(&xskt_server_addr))->sa_data;
                char stmp[16];

                s[0] = '\0';                  
                for(j=0; j<13; j++) {
                    sprintf(stmp, "%.2x:", *(ptr1++));
                    strcat(s, stmp);
                }
                sprintf(stmp, "%.2x", *ptr1); 
                strcat(s, stmp);
                AnscTrace("!!!!!!!!!! _xskt_connect error: server_addr=%s\n", s);
            }
            perror("_xskt_connect error");

            s_error = _xskt_get_last_error();

            if ( pMyObject->Mode & ANSC_SCTO_MODE_NO_BSP_NOTIFY_CONN_ERR == 0 )
            {
                pWorker->Notify
	    			(
		    			pWorker->hWorkerContext,
			    		ANSC_SCTOWO_EVENT_SOCKET_TIMEOUT,
				    	(ANSC_HANDLE)NULL
    				);
            }
            returnStatus = ANSC_STATUS_FAILURE;

            goto  EXIT2;
        }
    }
    else
    {
        _ansc_memset(&ansc_server_addr, 0, sizeof(ansc_server_addr));
        ansc_server_addr.sin_family      = ANSC_SOCKET_AF_INET;
        ansc_server_addr.sin_addr.s_addr = pMyObject->PeerAddress.Value;
        ansc_server_addr.sin_port        = _ansc_htons(pMyObject->PeerPort);

#ifdef _ANSC_IPV6_COMPATIBLE_
        if ( _ansc_connect(pMyObject->Socket, pansc_server_addrinfo->ai_addr, pansc_server_addrinfo->ai_addrlen) != 0 )
#else
        if ( _ansc_connect(pMyObject->Socket, (ansc_socket_addr*)&ansc_server_addr, sizeof(ansc_server_addr)) != 0 )
#endif
        {
            s_error = _ansc_get_last_error();

            AnscTrace("!!! Connect error: %d, %s !!!\n", s_error, strerror(s_error));

            if ( pMyObject->Mode & ANSC_SCTO_MODE_NO_BSP_NOTIFY_CONN_ERR == 0 )
            {
                pWorker->Notify
				    (
			    		pWorker->hWorkerContext,
		    			ANSC_SCTOWO_EVENT_SOCKET_TIMEOUT,
	    				(ANSC_HANDLE)NULL
    				);
            }

            returnStatus = ANSC_STATUS_FAILURE;

            goto  EXIT2;
        }
    }

    /*
     * We have gone so far that all socket operations succeeded, we want to allocate a buffer that
     * is big enough for any incoming message.
     */
    if ( !pMyObject->RecvBuffer && !(pMyObject->Mode & ANSC_SCTO_MODE_FOREIGN_BUFFER) )
    {
        pMyObject->RecvBuffer     = AnscAllocateMemory(pMyObject->RecvBufferSize);
        pMyObject->RecvPacketSize = 0;
        pMyObject->RecvOffset     = 0;

        if ( !pMyObject->RecvBuffer )
        {
            returnStatus = ANSC_STATUS_RESOURCES;

            goto  EXIT2;
        }
    }

    pMyObject->RecvBytesCount = 0;
    pMyObject->SendBytesCount = 0;
    pMyObject->LastRecvAt     = AnscGetTickInSeconds();
    pMyObject->LastSendAt     = AnscGetTickInSeconds();

    /*
     * If the compilation option '_ANSC_SOCKET_TLS_LAYER_' is enabled, we can simply let the ANSC
     * socket layer to perform the SSL/TLS functionality; otherwise, we need to prepare for doing
     * SSL/TLS internally.
     */
    if ( pMyObject->Mode & ANSC_SCTO_MODE_TLS_ENABLED )
    {
#ifdef _ANSC_USE_OPENSSL_
        pMyObject->bTlsEnabled = TRUE;
        if ( !openssl_init(SSL_CLIENT_CALLS) )
        {
            AnscTrace("AnscSctoEngage - openssl_init() failed!\n");
            returnStatus = ANSC_STATUS_FAILURE;
            goto  EXIT2;
        }

#else
        #ifdef  _ANSC_SOCKET_TLS_LAYER_
        {
            _ansc_en_usetls(pMyObject->Socket);

            pMyObject->bTlsEnabled = FALSE;
        }
        #else
        {
            pMyObject->hTlsScsIf   = (pMyObject->hTlsScsIf != NULL)? pMyObject->hTlsScsIf : AnscSocketTlsGetScsIf();
            pMyObject->bTlsEnabled = TRUE;
        }
        #endif
#endif
    }

    /*
     * To save the worker object from having to deal with blocking/non-blocking/async receiving
     * functions provided by underlying socket layer, we create a separate task to do that.
     */
    returnStatus =
        pMyObject->SpawnTask3
            (
                (ANSC_HANDLE)pMyObject,
                (void*      )pMyObject->RecvTask,
                (ANSC_HANDLE)pMyObject,
                ANSC_SCTO_RECV_TASK_NAME,
                USER_DEFAULT_TASK_PRIORITY,
                11*USER_DEFAULT_TASK_STACK_SIZE

            );
#ifdef _ANSC_USE_OPENSSL_
    if ( pMyObject->bTlsEnabled )
    {
   	    SSL *ssl = NULL;
   	    ssl = openssl_connect (pMyObject->Socket);
	    if ( !ssl )
		{

	        pMyObject->bTlsConnected = FALSE;
	        returnStatus = ANSC_STATUS_FAILURE;

	        //PANSC_SCTO_WORKER_OBJECT        pWorker      = (PANSC_SCTO_WORKER_OBJECT)pMyObject->hWorker;
            if ( pMyObject->Mode & ANSC_SCTO_MODE_NO_BSP_NOTIFY_CONN_ERR == 0 )
            {
                pWorker->Notify
                    (
                        pWorker->hWorkerContext,
                        ANSC_SCTOWO_EVENT_TLS_ERROR,
                        (ANSC_HANDLE)0L
                    );
            }
		}
	    else
	    {
			s_error = openssl_validate_certificate (pMyObject->Socket, pMyObject->HostName, ssl, SSL_CLIENT_CALLS);
		    if ( s_error == 0 )
		    {
		        AnscTrace("AnscSctoEngage - openssl_validate_certificate() failed %p.\n", ssl);

		        //PANSC_SCTO_WORKER_OBJECT        pWorker      = (PANSC_SCTO_WORKER_OBJECT      )pMyObject->hWorker;
                if ( pMyObject->Mode & ANSC_SCTO_MODE_NO_BSP_NOTIFY_CONN_ERR == 0 )
                {
	                pWorker->Notify
	                    (
	                        pWorker->hWorkerContext,
	                        ANSC_SCTOWO_EVENT_TLS_ERROR,
	                        (ANSC_HANDLE)NULL
	                    );
                }
		        returnStatus = ANSC_STATUS_FAILURE;
		    }

		    pMyObject->hTlsConnection = ssl;
		    pMyObject->bTlsConnected = TRUE;
	    }
    }
#else
    /*
     * If SSL/TLS is enabled, we should complete TLS handshake before returning from Engage(). This
     * behavior allows a single consistent API to used between this object and the worker object.
     * Since the handshake will take multiple messages to complete, we need to block the current
     * task until being notified by the TLS module.
     */
    if ( pMyObject->bTlsEnabled && pMyObject->hTlsScsIf )
    {
        pMyObject->bTlsConnected = FALSE;

        pMyObject->InitTlsClient((ANSC_HANDLE)pMyObject);
    }
#endif

    if ( returnStatus != ANSC_STATUS_SUCCESS )
    {
    	goto  EXIT2;
    }

    return  ANSC_STATUS_SUCCESS;


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

EXIT2:

	AnscTrace("AnscSctoEngage - failed with status %lu, socket error %d!\n", returnStatus, s_error);

    if ( pMyObject->Mode & ANSC_SCTO_MODE_XSOCKET )
    {
        _xskt_closesocket((XSKT_SOCKET)pMyObject->Socket);
    }
    else
    {
        _ansc_closesocket(pMyObject->Socket);
    }

EXIT1:

    if ( returnStatus != ANSC_STATUS_SUCCESS )
    {
        pMyObject->bActive = FALSE;

        pMyObject->Reset((ANSC_HANDLE)pMyObject);
    }

    return  returnStatus;
}
ANSC_STATUS
AnscDstoEngage
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    PANSC_DAEMON_SERVER_TCP_OBJECT  pMyObject    = (PANSC_DAEMON_SERVER_TCP_OBJECT)hThisObject;
    PANSC_DSTO_WORKER_OBJECT        pWorker      = (PANSC_DSTO_WORKER_OBJECT      )pMyObject->hWorker;
    int                             s_result     = 0;
#ifdef _ANSC_IPV6_COMPATIBLE_
    ansc_addrinfo                   ansc_hints           = {0};
    ansc_addrinfo*                  pansc_local_addrinfo = NULL;
    xskt_addrinfo                   xskt_hints           = {0};
    xskt_addrinfo*                  pxskt_local_addrinfo = NULL;
    USHORT                          usPort               = 0;
    char                            port[6]              = {0};
#else
    /*RDKB-6151, CID-24487,24794; initializing variable before use*/
    ansc_socket_addr_in             local_addr1 = {0};
    xskt_socket_addr_in             local_addr2 = {0};
#endif

    if ( pMyObject->bActive )
    {
        return  ANSC_STATUS_SUCCESS;
    }
    else if ( !pWorker )
    {
        return  ANSC_STATUS_UNAPPLICABLE;
    }
    else
    {
        pWorker->Init(pWorker->hWorkerContext);

        pMyObject->StartTime = AnscGetTickInSecondsAbs();
        pMyObject->bActive   = TRUE;
    }

    /*
     * The underlying socket wrapper may require an explicit startup() call, such is the case on
     * Microsoft windows platforms. The wrapper initialization has to done for each task. On most
     * real-time operating systems, this call is not required.
     */
    if ( pMyObject->Mode & ANSC_DSTO_MODE_XSOCKET )
    {
        AnscStartupXsocketWrapper((ANSC_HANDLE)pMyObject);
    }
    else
    {
        AnscStartupSocketWrapper((ANSC_HANDLE)pMyObject);
    }
    
#ifdef _ANSC_IPV6_COMPATIBLE_

    if ( pMyObject->Mode & ANSC_DSTO_MODE_XSOCKET )
    {
        xskt_hints.ai_family   = AF_UNSPEC;
        xskt_hints.ai_socktype = XSKT_SOCKET_STREAM;
        xskt_hints.ai_flags    = AI_PASSIVE | AI_ADDRCONFIG;

        usPort = pMyObject->GetHostPort((ANSC_HANDLE)pMyObject);
        _ansc_sprintf(port, "%d", usPort);
        CcspTraceInfo(("!!! Host Name: %s, Host Port: %s !!!\n", pMyObject->HostName, port));

        if ( _xskt_getaddrinfo
                (
                    pMyObject->HostName[0] ? pMyObject->HostName : "::", 
                    port,
                    &xskt_hints,
                    &pxskt_local_addrinfo
                ) 
            )
        {
            CcspTraceError(("!!! error 1 !!!\n"));

            returnStatus = ANSC_STATUS_FAILURE;
            
            goto  EXIT1;
        }
        
        pMyObject->pHostAddr2 = pxskt_local_addrinfo;
    }
    else
    {
        ansc_hints.ai_family   = AF_UNSPEC;
        ansc_hints.ai_socktype = ANSC_SOCKET_STREAM;
        ansc_hints.ai_flags    = AI_PASSIVE | AI_ADDRCONFIG;

        usPort = pMyObject->GetHostPort((ANSC_HANDLE)pMyObject);
        _ansc_sprintf(port, "%d", usPort);
        CcspTraceInfo(("!!! Host Name: %s, Host Port: %s !!!\n", pMyObject->HostName, port));

        if ( _ansc_getaddrinfo
                (
                    pMyObject->HostName[0] ? pMyObject->HostName : "::",
                    port,
                    &ansc_hints,
                    &pansc_local_addrinfo
                ) 
            )
        {
            returnStatus = ANSC_STATUS_FAILURE;

            goto  EXIT1;
        }
        
        pMyObject->pHostAddr1 = pansc_local_addrinfo;
    }

#endif

    /*
     * To engage the Tcp Daemon, we need to perform following acts in the respective order:
     *
     *      (1) create the os-dependent socket
     *      (2) manufacture and start all the engines objects
     *      (3) manufacture the global socket object pool
     *      (4) bind to the socket and listen on it
     */
    if ( pMyObject->Mode & ANSC_DSTO_MODE_XSOCKET )
    {
#ifdef _ANSC_IPV6_COMPATIBLE_
        pMyObject->Socket = _xskt_socket(pxskt_local_addrinfo->ai_family, pxskt_local_addrinfo->ai_socktype, 0);
#else
        pMyObject->Socket = _xskt_socket(XSKT_SOCKET_AF_INET, XSKT_SOCKET_STREAM, 0);
#endif
    }
    else
    {
#ifdef _ANSC_IPV6_COMPATIBLE_
        pMyObject->Socket = _ansc_socket(pansc_local_addrinfo->ai_family, pansc_local_addrinfo->ai_socktype, 0);
#else
        pMyObject->Socket = _ansc_socket(ANSC_SOCKET_AF_INET, ANSC_SOCKET_STREAM, 0);
#endif
    }

    if ( ((pMyObject->Socket == XSKT_SOCKET_INVALID_SOCKET) &&  (pMyObject->Mode & ANSC_DSTO_MODE_XSOCKET)) ||
         ((pMyObject->Socket == ANSC_SOCKET_INVALID_SOCKET) && !(pMyObject->Mode & ANSC_DSTO_MODE_XSOCKET)) )
    {
        returnStatus = ANSC_STATUS_FAILURE;

        goto  EXIT1;
    }

    _ansc_en_reuseaddr(pMyObject->Socket);

#ifndef _ANSC_IPV6_COMPATIBLE_
    if ( pMyObject->Mode & ANSC_DSTO_MODE_XSOCKET )
    {
        local_addr2.sin_family = XSKT_SOCKET_AF_INET;
        local_addr2.sin_port   = _xskt_htons(pMyObject->HostPort);

        if ( pMyObject->HostAddress.Value == 0 )
        {
            ((pansc_socket_addr_in)&local_addr2)->sin_addr.s_addr = XSKT_SOCKET_ANY_ADDRESS;
        }
        else
        {
            ((pansc_socket_addr_in)&local_addr2)->sin_addr.s_addr = pMyObject->HostAddress.Value;
        }
    }
    else
    {
        local_addr1.sin_family = ANSC_SOCKET_AF_INET;
        local_addr1.sin_port   = _ansc_htons(pMyObject->HostPort);

        if ( pMyObject->HostAddress.Value == 0 )
        {
            local_addr1.sin_addr.s_addr = ANSC_SOCKET_ANY_ADDRESS;
        }
        else
        {
            local_addr1.sin_addr.s_addr = pMyObject->HostAddress.Value;
        }
    }
#endif

#if !defined(_ANSC_KERNEL) || !defined(_ANSC_LINUX)
    if ( pMyObject->Mode & ANSC_DSTO_MODE_XSOCKET )
    {
#ifdef _ANSC_IPV6_COMPATIBLE_
        s_result = _xskt_bind(pMyObject->Socket, pxskt_local_addrinfo->ai_addr, pxskt_local_addrinfo->ai_addrlen);
#else
        AnscTrace("AnscDstoEngage -- the address is 0x%lX:%d, familty %d.\n", _ansc_ntohl(local_addr2.sin_addr.s_addr), _ansc_ntohs(local_addr2.sin_port), local_addr2.sin_family);
        s_result = _xskt_bind(pMyObject->Socket, (xskt_socket_addr*)&local_addr2, sizeof(local_addr2));
#endif
    }
    else
    {
#ifdef _ANSC_IPV6_COMPATIBLE_
        s_result = _ansc_bind(pMyObject->Socket, pansc_local_addrinfo->ai_addr, pansc_local_addrinfo->ai_addrlen);
#else
        s_result = _ansc_bind(pMyObject->Socket, (ansc_socket_addr*)&local_addr1, sizeof(local_addr1));
#endif
    }
#else
	if ( pMyObject->Mode & ANSC_DSTO_MODE_XSOCKET )
    {
        while ( _xskt_bind(pMyObject->Socket, (ansc_socket_addr*)&local_addr2, sizeof(local_addr2)) != 0 )
        {
            AnscTrace
				(
					"AnscDstoEngage -- failure to bind try again !socket %d family %d port %d address %X \n",
					pMyObject->Socket,
					local_addr2.sin_family,
                    local_addr2.sin_port,
					((pansc_socket_addr_in)&local_addr2)->sin_addr.s_addr
				);

            AnscSleep(10);
        }
    }
    else
    {
        while ( _ansc_bind(pMyObject->Socket, (ansc_socket_addr*)&local_addr1, sizeof(local_addr1)) != 0 )
        {
            AnscTrace
				(
					"AnscDstoEngage -- failure to bind try again !socket %d family %d port %d address %X \n",
					pMyObject->Socket,
					local_addr1.sin_family,
                    local_addr1.sin_port,
					local_addr1.sin_addr.s_addr
				);

            AnscSleep(10);
        }
    }
#endif

    if ( s_result != 0 )
    {
		AnscTrace
            (
                "AnscDstoEngage -- failed to bind to the socket, error code is %d!!!\n",
                (pMyObject->Mode & ANSC_DSTO_MODE_XSOCKET) ? _xskt_get_last_error() : _ansc_get_last_error()
            );

        returnStatus = ANSC_STATUS_FAILURE;

        goto  EXIT2;
    }

    pMyObject->ManufactureEnginePool((ANSC_HANDLE)pMyObject);
    pMyObject->ManufactureSocketPool((ANSC_HANDLE)pMyObject);
    pMyObject->StartEngines         ((ANSC_HANDLE)pMyObject);

    if ( pMyObject->Mode & ANSC_DSTO_MODE_XSOCKET )
    {
        s_result = _xskt_listen(pMyObject->Socket, ANSC_SOCKET_BACKLOG_VALUE);
    }
    else
    {
        s_result = _ansc_listen(pMyObject->Socket, ANSC_SOCKET_BACKLOG_VALUE);
    }

    if ( s_result != 0 )
    {
		AnscTrace("AnscDstoEngage -- failed to listen on the socket!\n");

        returnStatus = ANSC_STATUS_FAILURE;

        goto  EXIT2;
    }

    /*
     * If the compilation option '_ANSC_SOCKET_TLS_LAYER_' is enabled, we can simply let the ANSC
     * socket layer to perform the SSL/TLS functionality; otherwise, we need to prepare for doing
     * SSL/TLS internally.
     */
    if ( pMyObject->Mode & ANSC_DSTO_MODE_TLS_ENABLED )
    {
#ifdef _ANSC_USE_OPENSSL_
        pMyObject->bTlsEnabled = TRUE;
        if ( !openssl_init(SSL_SERVER_CALLS) )
        {
        	AnscTrace("AnscSctoEngage - openssl_init() failed!\n");
            returnStatus = ANSC_STATUS_FAILURE;
            goto  EXIT2;
        }

#else
        #ifdef  _ANSC_SOCKET_TLS_LAYER_
        {
            _ansc_en_usetls(pMyObject->Socket);

            pMyObject->bTlsEnabled = FALSE;
        }
        #else
        {
            pMyObject->hTlsScsIf   = (pMyObject->hTlsScsIf != NULL)? pMyObject->hTlsScsIf : AnscSocketTlsGetScsIf();
            pMyObject->bTlsEnabled = TRUE;
            pMyObject->bTlsReqCert = (pMyObject->Mode & ANSC_DSTO_MODE_TLS_REQ_CERT);
        }
        #endif
#endif
    }

    AnscResetEvent(&pMyObject->AcceptEvent);
    returnStatus =
        pMyObject->SpawnTask3
            (
                (ANSC_HANDLE)pMyObject,
                (void*      )pMyObject->AcceptTask,
                (ANSC_HANDLE)pMyObject,
                ANSC_DSTO_ACCEPT_TASK_NAME,
                USER_DEFAULT_TASK_PRIORITY,
                2*USER_DEFAULT_TASK_STACK_SIZE

            );

    return  ANSC_STATUS_SUCCESS;


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

EXIT2:

    if ( pMyObject->Mode & ANSC_DSTO_MODE_XSOCKET )
    {
        _xskt_closesocket(pMyObject->Socket);
    }
    else
    {
        _ansc_closesocket(pMyObject->Socket);
    }

EXIT1:

    if ( returnStatus != ANSC_STATUS_SUCCESS )
    {
        pMyObject->bActive = FALSE;
    }

    return  returnStatus;
}
ANSC_STATUS
AnscDktoTsaRecvAppMessage
    (
        ANSC_HANDLE                 hThisObject,
        ANSC_HANDLE                 hMessageBdo
    )
{
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    PANSC_DAEMON_SOCKET_TCP_OBJECT  pMyObject    = (PANSC_DAEMON_SOCKET_TCP_OBJECT)hThisObject;
    PANSC_DAEMON_SERVER_TCP_OBJECT  pServer      = (PANSC_DAEMON_SERVER_TCP_OBJECT)pMyObject->hDaemonServer;
    PANSC_DAEMON_ENGINE_TCP_OBJECT  pEngine      = (PANSC_DAEMON_ENGINE_TCP_OBJECT)pMyObject->hDaemonEngine;
    PANSC_DSTO_WORKER_OBJECT        pWorker      = (PANSC_DSTO_WORKER_OBJECT      )pServer->hWorker;
    PANSC_BUFFER_DESCRIPTOR         pPayloadBdo  = (PANSC_BUFFER_DESCRIPTOR       )hMessageBdo;
    void*                           pRecvBuffer  = (void*                         )NULL;
    ANSC_HANDLE                     hRecvHandle  = (ANSC_HANDLE                   )NULL;
    ULONG                           ulRecvSize   = (ULONG                         )0;
    ULONG                           ulLeftSize   = (ULONG                         )AnscBdoGetBlockSize(pPayloadBdo);
    ULONG                           ulCopySize   = (ULONG                         )0;
    ULONG                           ulServingT1  = 0;
    ULONG                           ulServingT2  = 0;
    ULONG                           ulWaitCount  = 0;

    /*
     * Since the TLS handshake is done in the asynchronous task instead of the socket_recv task,
     * it's possible that we start receiving TLS client data traffic (i.e. HTTP) before handshake
     * task considers the handshaking is done. To accommodate such race condition, we need to sleep
     * for a while if there's no buffer available.
     */
    while ( !pMyObject->GetRecvBuffer
                (
                    (ANSC_HANDLE)pMyObject,
                    &ulRecvSize
                ) )
    {
        AnscSleep(10);

        ulWaitCount++;

        if ( ulWaitCount > 30 ) /* sleep for 300ms */
        {
            returnStatus = ANSC_STATUS_INTERNAL_ERROR;

            goto  EXIT1;
        }
    }

    while ( ulLeftSize > 0 )
    {
        pRecvBuffer =
            pMyObject->GetRecvBuffer
                (
                    (ANSC_HANDLE)pMyObject,
                    &ulRecvSize
                );

        if ( !pRecvBuffer )
        {
            returnStatus =
                pWorker->Notify
                    (
                        pWorker->hWorkerContext,
                        (ANSC_HANDLE)pMyObject,
                        ANSC_DSTOWO_EVENT_RESOURCES,
                        (ANSC_HANDLE)NULL
                    );

            break;
        }
        else if ( ulRecvSize == 0 )
        {
            pMyObject->ToClean((ANSC_HANDLE)pMyObject, TRUE, 2);

            break;
        }

        if ( ulRecvSize >= ulLeftSize )
        {
            ulCopySize = ulLeftSize;
        }
        else
        {
            ulCopySize = ulRecvSize;
        }

        if ( TRUE )
        {
            AnscCopyMemory
                (
                    pRecvBuffer,
                    AnscBdoGetBlock(pPayloadBdo),
                    ulCopySize
                );

            AnscBdoShrinkRight(pPayloadBdo, ulCopySize);

            ulLeftSize -= ulCopySize;
        }

        pMyObject->RecvBytesCount += ulCopySize;
        pMyObject->LastRecvAt      = AnscGetTickInSecondsAbs();

        /*
         * We have successfully transferred the received data into the buffer supplied by the
         * socket owener though may not use up the while buffer. Now is time to notify our loyal
         * socket owner about this exciting event.
         */
        ulServingT1  = AnscGetTickInMilliSeconds();
        returnStatus =
            pMyObject->Recv
                (
                    (ANSC_HANDLE)pMyObject,
                    pRecvBuffer,
                    ulCopySize
                );
        ulServingT2  = AnscGetTickInMilliSeconds();

        pEngine->AvgServingTime =
            (pEngine->AvgServingTime == 0)? (ulServingT2 - ulServingT1) : ((ulServingT2 - ulServingT1) + pEngine->AvgServingTime * 7) / 8;
        pEngine->TscCount++;
    }

    goto  EXIT1;


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

EXIT1:

    if ( pPayloadBdo )
    {
        AnscFreeBdo((ANSC_HANDLE)pPayloadBdo);
    }

    return  returnStatus;
}
ANSC_STATUS
bbhmDownloadStartDiagTask

    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus       = ANSC_STATUS_SUCCESS;
    PBBHM_DOWNLOAD_DIAG_OBJECT      pMyObject          = (PBBHM_DOWNLOAD_DIAG_OBJECT)hThisObject;
    PDSLH_TR143_DOWNLOAD_DIAG_STATS pStats             = (PDSLH_TR143_DOWNLOAD_DIAG_STATS)&pMyObject->DownloadDiagStats;
    char                            ipv6ref[64]        = {0};
    char*                           pHost              = NULL;
    char*                           pServ              = NULL;
    char*                           pPath              = NULL;
    ULONG                           uCount             = 500;  /* half second */
    XSKT_SOCKET                     aSocket            = XSKT_SOCKET_INVALID_SOCKET;
    int                             s_result           = 0;
    char                            buffer[1024]       = { 0 };
    ULONG                           ulSize             = 0;
    char*                           recv_buffer        = NULL;
    ULONG                           recv_size          = 0;
	int								tos				   = 0;
    xskt_addrinfo                   hints;
    xskt_addrinfo                   *servInfo   	   = NULL;
    xskt_addrinfo                   *cliInfo    	   = NULL;

    if ( !pMyObject->bActive )
    {
        return  ANSC_STATUS_FAILURE;
    }

    pMyObject->bDownNotifyNeeded = FALSE;

    /* make sure previous diag is done */
    while( pMyObject->bDownDiagOn )
    {
        AnscSleep(uCount);

        if ( !pMyObject->bActive )
        {
            returnStatus = ANSC_STATUS_FAILURE;

            goto done;
        }
    }

    /* init socket wrapper */
    AnscStartupXsocketWrapper((ANSC_HANDLE)pMyObject);

    /* turn on the diag */
    pMyObject->bDownDiagOn         = TRUE;
    
    /* reset the stats */
    DslhResetDownloadDiagStats((pStats));

    pStats->DiagStates = DSLH_TR143_DIAGNOSTIC_Requested;

    if ( pMyObject->bStopDownDiag )
    {
        returnStatus = ANSC_STATUS_FAILURE;
        goto done;
    }

    /* parse the download http url */
    if (ParseHttpURL(pMyObject->DownloadDiagInfo.DownloadURL,
                &pHost, &pServ, &pPath) != 0)
    {
		/* if the function fail, memory should not allcated, 
		 * but the the Pointer's value is uncertain */
		pHost = pServ = pPath = NULL;
		
        pMyObject->bDownNotifyNeeded = TRUE;
        pStats->DiagStates = DSLH_TR143_DIAGNOSTIC_Error_InitConnectionFailed;

        returnStatus = ANSC_STATUS_FAILURE;
        goto done;
    }

	/* resolution the HTTP server's hostname/service to sockaddrinfo */
    AnscZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_UNSPEC; /* XXX: xsocket wrapper has no XSKT_SOCKET_AF_UNSPEC */
    hints.ai_socktype = SOCK_STREAM;
    if (_xskt_getaddrinfo(pHost, pServ, &hints, &servInfo) != 0)
    {
		servInfo = NULL;

        pMyObject->bDownNotifyNeeded = TRUE;
        pStats->DiagStates = DSLH_TR143_DIAGNOSTIC_Error_InitConnectionFailed;

        returnStatus = ANSC_STATUS_FAILURE;
        goto done;
    }

    /* create the socket */
    aSocket = (XSKT_SOCKET)_xskt_socket(servInfo->ai_family, 
    		servInfo->ai_socktype, servInfo->ai_protocol);
    if ( aSocket == XSKT_SOCKET_INVALID_SOCKET )
    {
        pMyObject->bDownNotifyNeeded = TRUE;
        pStats->DiagStates = DSLH_TR143_DIAGNOSTIC_Error_InitConnectionFailed;

        returnStatus = ANSC_STATUS_FAILURE;
        goto done;
    }

	/* bind local address if need */
#if 0
    if (GetAddressByDmlPath(pMyObject->DownloadDiagInfo.Interface, 
			localAddr, sizeof(localAddr)) == 0)
#else
	if (_ansc_strlen(pMyObject->DownloadDiagInfo.IfAddrName) > 0)
#endif
	{
        AnscZeroMemory(&hints, sizeof(hints));
		hints.ai_family = servInfo->ai_family;
		hints.ai_socktype = servInfo->ai_socktype;

		if ((s_result = _xskt_getaddrinfo(pMyObject->DownloadDiagInfo.IfAddrName, "", &hints, &cliInfo)) != 0
				|| _xskt_bind(aSocket, cliInfo->ai_addr, cliInfo->ai_addrlen) != 0)
		{
			if (s_result != 0)
				cliInfo = NULL;
			
	        pMyObject->bDownNotifyNeeded = TRUE;
	        pStats->DiagStates = DSLH_TR143_DIAGNOSTIC_Error_InitConnectionFailed;

	        returnStatus = ANSC_STATUS_FAILURE;
	        goto done;
	    }
	}
	
	/* DSCP */
	if (pMyObject->DownloadDiagInfo.DSCP > 0 && pMyObject->DownloadDiagInfo.DSCP < 64)
	{
		/* 6bits DSCP, and 2bits ENC */
		tos = pMyObject->DownloadDiagInfo.DSCP << 2;
		
		/* XXX: no XSKT_SOCKET_SOL_IP_TOS or XSKT_SOCKET_IP_TOS
		 * and infact IPPROTO_IP and SOL_XXX is not same level,
		 * so the name XSKT_SOCKET_SOL_IPPROTO_IP is not approciate.*/

		if (servInfo->ai_family == XSKT_SOCKET_AF_INET)
		{
			if (_xskt_setsocketopt(aSocket, XSKT_SOCKET_SOL_IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) != 0)
				AnscTraceWarning(("Fail to set IPv4 DSCP.\n"));
		}
		else if (servInfo->ai_family == XSKT_SOCKET_AF_INET6)
		{
			if (_xskt_setsocketopt(aSocket, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos)) != 0)
				AnscTraceWarning(("Fail to set IPv6 DSCP.\n"));
		}
	}

	/* ethernet priority */
	/* TODO: need 802.1d support */

    AnscGetSystemTime(&pStats->TCPOpenRequestTime);

	/* connect HTTP server */
    if ( _xskt_connect(aSocket, servInfo->ai_addr, servInfo->ai_addrlen) != 0 )
    {
        /* failed to connect the server */
        AnscTraceWarning(("Unable to connect to the http server.\n"));

        pMyObject->bDownNotifyNeeded = TRUE;
        pStats->DiagStates = DSLH_TR143_DIAGNOSTIC_Error_NoResponse;

        returnStatus = ANSC_STATUS_FAILURE;

        AnscGetSystemTime(&pStats->TCPOpenResponseTime);
        
        goto done;
    }
    
    AnscGetSystemTime(&pStats->TCPOpenResponseTime);

    /* record HTTP request time */
    AnscGetSystemTime(&pStats->ROMTime);

	/*
	 * according to RFC2396, "host" field in HTTP header for IPv6 addresss 
	 * should be a IPv6 Reference. 
	 * 
	 * 	 host		   = hostname | IPv4address | IPv6reference
	 *   ipv6reference = "[" IPv6address "]"
	 */
	if (IsIPv6Address(pHost))
	{
		snprintf(ipv6ref, sizeof(ipv6ref), "[%s]", pHost);
		_ansc_sprintf(buffer, http_get_request2, pPath, ipv6ref, pServ);
	}
	else
	{
		_ansc_sprintf(buffer, http_get_request2, pPath, pHost, pServ);
	}

	/* send the HTTP request */
    ulSize   = AnscSizeOfString(buffer);
    s_result = _xskt_send(aSocket, buffer, (int)ulSize, 0);

#ifdef _DEBUG

    AnscTraceWarning(("******** Download Request **************\n"));
    AnscTraceWarning((buffer));
    AnscTraceWarning(("\n******************************************\n"));

#endif

    if ( s_result == XSKT_SOCKET_ERROR || s_result < (int)ulSize )
    {
        /* failed to send the request */
        AnscTraceWarning(("Failed to send request to the http server.\n"));

        pMyObject->bDownNotifyNeeded = TRUE;
        pStats->DiagStates = DSLH_TR143_DIAGNOSTIC_Error_InitConnectionFailed;

        returnStatus = ANSC_STATUS_FAILURE;
        goto done;
    }

    /* receive the response */
    recv_buffer = (char*)AnscAllocateMemory(DOWNLOAD_SINGLE_BUFFER_SIZE + 1);

    if ( recv_buffer == NULL )
    {
        /* failed to send the request */
        AnscTraceWarning(("Failed to allocate memory.\n"));

        pMyObject->bDownNotifyNeeded = TRUE;
        pStats->DiagStates = DSLH_TR143_DIAGNOSTIC_Error_InitConnectionFailed;

        returnStatus = ANSC_STATUS_FAILURE;
        goto done;
    }

    recv_size   = DOWNLOAD_SINGLE_BUFFER_SIZE;
    s_result    = _xskt_recv(aSocket, recv_buffer, recv_size, 0);

    AnscGetSystemTime(&pStats->BOMTime);

    /* check whether it succededd or not */
    if ( s_result <= 0 || _ansc_strstr(recv_buffer, "HTTP/1.1 2") != recv_buffer )
    {
        /* failed to receive the request */
        AnscTraceWarning(("Failed to recv or not 200 OK.\n"));

        pMyObject->bDownNotifyNeeded = TRUE;
        pStats->DiagStates = DSLH_TR143_DIAGNOSTIC_Error_TransferFailed;

        returnStatus = ANSC_STATUS_FAILURE;
        goto done;
    }

    while(s_result > 0)
    {
#if _DEBUG
		recv_buffer[s_result] = '\0'; /* allocated one more byte, so no problem */
		AnscTraceWarning(("%s", recv_buffer));
#endif

        AnscGetSystemTime(&pStats->EOMTime);
        pStats->TestBytesReceived += s_result;
        if ( pMyObject->bStopDownDiag )
        {
            returnStatus = ANSC_STATUS_FAILURE;
            goto done;
        }

        recv_size   = DOWNLOAD_SINGLE_BUFFER_SIZE;
        s_result    = _xskt_recv(aSocket, recv_buffer, recv_size, 0);

        if ( s_result < 0 )
        {
            /* failed to receive the request */
            AnscTraceWarning(("Failed to recv packet.\n"));

            pMyObject->bDownNotifyNeeded = TRUE;
            pStats->DiagStates = DSLH_TR143_DIAGNOSTIC_Error_TransferFailed;

            returnStatus = ANSC_STATUS_FAILURE;
            goto done;
        }
    }

    /* succeeded */
    pMyObject->bDownNotifyNeeded = TRUE;
    pStats->DiagStates           = DSLH_TR143_DIAGNOSTIC_Completed;

done:
    /* clear resources if need */
    if (aSocket != XSKT_SOCKET_INVALID_SOCKET)
        _xskt_closesocket(aSocket);
    if (recv_buffer != NULL)
        AnscFreeMemory(recv_buffer);
    if (servInfo)
        _xskt_freeaddrinfo(servInfo);
    if (cliInfo)
        _xskt_freeaddrinfo(cliInfo);
	if (pHost)
		AnscFreeMemory(pHost);
	if (pServ)
		AnscFreeMemory(pServ);
	if (pPath)
		AnscFreeMemory(pPath);
    
    if ( pMyObject->bDownNotifyNeeded )
    {
        CosaSendDiagCompleteSignal();
    }

    /* if the task is stopped, reset the stats */
    if ( pMyObject->bStopDownDiag )
    {
        DslhResetDownloadDiagStats((&pMyObject->DownloadDiagStats));        
    }

    pMyObject->DownloadDiagInfo.DiagnosticsState = pStats->DiagStates;
        
    /* clear flags */
    pMyObject->bDownNotifyNeeded   = FALSE;
    pMyObject->bDownDiagOn         = FALSE; 
    pMyObject->bStopDownDiag       = FALSE;

    return returnStatus;
}
ANSC_STATUS
BbhmDiagipStart
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    PBBHM_DIAG_IP_PING_OBJECT       pMyObject    = (PBBHM_DIAG_IP_PING_OBJECT)hThisObject;
    PDSLH_PING_INFO                 pDiagInfo    = (PDSLH_PING_INFO)pMyObject->hDslhDiagInfo;
    PBBHM_IP_PING_PROPERTY          pProperty    = (PBBHM_IP_PING_PROPERTY  )&pMyObject->Property;
    PBBHM_IP_PING_TDO_OBJECT        pStateTimer  = (PBBHM_IP_PING_TDO_OBJECT)pMyObject->hStateTimer;
    PBBHM_IP_PING_SINK_OBJECT       pSink        = (PBBHM_IP_PING_SINK_OBJECT)pMyObject->hSinkObject;
    PANSC_XSOCKET_OBJECT            pSocket      = (PANSC_XSOCKET_OBJECT     )pSink->GetXsocket((ANSC_HANDLE)pSink);
    ULONG                           numPkts      = pProperty->NumPkts;
    ULONG                           pktSize      = pProperty->PktSize;
    PCHAR                           pSendBuffer  = pMyObject->hSendBuffer;
    ULONG                           i            = 0;
    PICMPV4_ECHO_MESSAGE            pIcmpHeader  = NULL;
    ULONG                           StartTime    = 0;
    UCHAR                           SrcIp[4]     = {0, 0, 0, 0};

    if ( !pMyObject->bActive )
    {
        pProperty->Status = BBHM_IP_PING_STATUS_ABORT;

        pMyObject->Stop(hThisObject);

        return  ANSC_STATUS_FAILURE;
    }

    pMyObject->ResetPropertyCounter((ANSC_HANDLE)pMyObject);

    pSocket->SetPeerName     ((ANSC_HANDLE)pSocket, pProperty->pDstAddrName);
    pSocket->SetHostName     ((ANSC_HANDLE)pSocket, pProperty->pSrcAddrName);
    /*
    pSocket->SetHostAddress  ((ANSC_HANDLE)pSocket, SrcIp                 );
    pSocket->SetHostPort     ((ANSC_HANDLE)pSocket, 0                     );
    */

    /*pSocket->SetTransportType((ANSC_HANDLE)pSocket, ICMP_TRANSPORT        );*/
    pSocket->SetType         ((ANSC_HANDLE)pSocket, ANSC_XSOCKET_TYPE_RAW );
    pSocket->SetMode         ((ANSC_HANDLE)pSocket, 0                     );

    pSocket->SetXsink        ((ANSC_HANDLE)pSocket, (ANSC_HANDLE)pSink    );

    /*
     * The underlying socket wrapper may require an explicit startup() call, such is the case on
     * Microsoft windows platforms. The wrapper initialization has to done for each task. On most
     * real-time operating systems, this call is not required.
     */
    AnscStartupXsocketWrapper((ANSC_HANDLE)pMyObject);

    /* For IPv4/IPv6 compatible purpose we shall resolve the address first */
	returnStatus = BbhmDiagResolvAddr(hThisObject);

    if ( returnStatus != ANSC_STATUS_SUCCESS )
    {
        pProperty->Status = BBHM_IP_PING_STATUS_ERROR_HostName;

        pMyObject->Stop(hThisObject);

        return ANSC_STATUS_FAILURE;
    }

    pMyObject->IPProtocol = pSocket->GetIpProtocol((ANSC_HANDLE)pSocket);

    if ( pMyObject->IPProtocol == XSKT_SOCKET_AF_INET )
    {
        pSocket->SetTransportType((ANSC_HANDLE)pSocket, IP4_PROTOCOL_ICMP);
    }
    else if ( pMyObject->IPProtocol == XSKT_SOCKET_AF_INET6 )
    {
        pSocket->SetTransportType((ANSC_HANDLE)pSocket, IP6_PROTOCOL_ICMP);
    }
    else
    {
        pProperty->Status = BBHM_IP_PING_STATUS_ABORT;

        pMyObject->Stop(hThisObject);

        return  ANSC_STATUS_FAILURE;
    }

    /*
     * We shall open the socket and listen on it right away. Since we're still in the context of
     * initialiation, the wrapper module must be aware of the fact that the socket is opened before
     * the first call returns.
     */
    returnStatus = pSocket->Bind((ANSC_HANDLE)pSocket);

    if ( returnStatus != ANSC_STATUS_SUCCESS )
    {
        pProperty->Status = BBHM_IP_PING_STATUS_ABORT;

        pMyObject->Stop(hThisObject);

        return  ANSC_STATUS_FAILURE;
    }

    returnStatus = pSocket->Open((ANSC_HANDLE)pSocket); /* Create recv task */

    if ( returnStatus != ANSC_STATUS_SUCCESS )
    {
        AnscTrace("Socket Open Failed!\n");
        pProperty->Status = BBHM_IP_PING_STATUS_ABORT;

        pMyObject->Stop(hThisObject);

        return  ANSC_STATUS_FAILURE;
    }

    if ( !pSendBuffer )
    {
        returnStatus = ANSC_STATUS_FAILURE;
        pProperty->Status = BBHM_IP_PING_STATUS_ABORT;

        pMyObject->Stop(hThisObject);

        return  ANSC_STATUS_FAILURE;
    }

    /* Set DSCP */
    if ( pDiagInfo->DSCP != 0 )
    {
        pSocket->ApplyDSCP((ANSC_HANDLE)pSocket, pDiagInfo->DSCP);
    }

    AnscSleep(100);

    if ( pMyObject->IPProtocol == XSKT_SOCKET_AF_INET )
    {
        pIcmpHeader = (PICMPV4_ECHO_MESSAGE)pMyObject->hSendBuffer;

        AnscIcmpv4EchoSetType        (pIcmpHeader, ICMP_TYPE_ECHO_REQUEST   );
        AnscIcmpv4EchoSetCode        (pIcmpHeader, 0                        );
        AnscIcmpv4EchoSetId          (pIcmpHeader, tempId                   );
        AnscIcmpv4EchoSetSeqNumber   (pIcmpHeader, (USHORT)pMyObject->GetPktsSent((ANSC_HANDLE)pMyObject));

        for ( i = 0; i < pktSize; i++ )
        {
            ((PUCHAR)pMyObject->hSendBuffer)[i + sizeof(ICMPV4_HEADER)] = (UCHAR)i;
        }

        AnscIcmpv4EchoSetChecksum   (pIcmpHeader, 0                                 );
        AnscIcmpv4CalculateChecksum (((PICMPV4_HEADER)pIcmpHeader), pktSize + sizeof(ICMPV4_HEADER));
    }
    else if ( pMyObject->IPProtocol == XSKT_SOCKET_AF_INET6 )
    {
        pIcmpHeader = (PICMPV6_ECHO_MESSAGE)pMyObject->hSendBuffer;

        AnscIcmpv6EchoSetType        (pIcmpHeader, ICMP6_TYPE_ECHO_REQUEST  );
        AnscIcmpv6EchoSetCode        (pIcmpHeader, 0                        );
        AnscIcmpv6EchoSetId          (pIcmpHeader, tempId                   );
        AnscIcmpv6EchoSetSeqNumber   (pIcmpHeader, (USHORT)pMyObject->GetPktsSent((ANSC_HANDLE)pMyObject));

        for ( i = 0; i < pktSize; i++ )
        {
            ((PUCHAR)pMyObject->hSendBuffer)[i + sizeof(ICMPV6_HEADER)] = (UCHAR)i;
        }
    }

    pStateTimer->SetTimerType((ANSC_HANDLE)pStateTimer, ANSC_TIMER_TYPE_SPORADIC);
    pStateTimer->SetInterval ((ANSC_HANDLE)pStateTimer, pProperty->TimeBetween  );
    pStateTimer->SetCounter  ((ANSC_HANDLE)pStateTimer, pProperty->NumPkts      );
/*
    pSocket->SetPeerAddress  ((ANSC_HANDLE)pSocket    , pProperty->DstIp.Dot    );
    pSocket->SetPeerPort     ((ANSC_HANDLE)pSocket    , 0                       );
*/
    pMyObject->SetStatus((ANSC_HANDLE)pMyObject, BBHM_IP_PING_STATUS_RUNNING);

    pStateTimer->Start       ((ANSC_HANDLE)pStateTimer);

    StartTime = AnscGetTickInMilliSeconds();

    if ( pMyObject->IPProtocol == XSKT_SOCKET_AF_INET )
    {
        returnStatus =
            pMyObject->AddEchoEntry
                (
                    (ANSC_HANDLE)pMyObject,
                    AnscIcmpv4EchoGetSeqNumber(pIcmpHeader),
                    StartTime
                );

        returnStatus =
            pMyObject->Send
                (
                    (ANSC_HANDLE)pMyObject,
                    (ANSC_HANDLE)pMyObject->hSinkObject,
                    (PVOID)pMyObject->hSendBuffer,
                    pktSize + sizeof(ICMPV4_HEADER)
                );
    }
    else if ( pMyObject->IPProtocol == XSKT_SOCKET_AF_INET6 )
    {
        returnStatus =
            pMyObject->AddEchoEntry
                (
                    (ANSC_HANDLE)pMyObject,
                    AnscIcmpv6EchoGetSeqNumber(pIcmpHeader),
                    StartTime
                );

        returnStatus =
            pMyObject->Send
                (
                    (ANSC_HANDLE)pMyObject,
                    (ANSC_HANDLE)pMyObject->hSinkObject,
                    (PVOID)pMyObject->hSendBuffer,
                    pktSize + sizeof(ICMPV6_HEADER)
                );
    }

    pProperty->PktsSent++;

    return  returnStatus;

}
ANSC_STATUS
BbhmDiagipStop
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    PBBHM_DIAG_IP_PING_OBJECT       pMyObject    = (PBBHM_DIAG_IP_PING_OBJECT     )hThisObject;
    PBBHM_IP_PING_PROPERTY          pProperty    = (PBBHM_IP_PING_PROPERTY        )&pMyObject->Property;
    PBBHM_IP_PING_TDO_OBJECT        pStateTimer  = (PBBHM_IP_PING_TDO_OBJECT      )pMyObject->hStateTimer;
    PBBHM_IP_PING_SINK_OBJECT       pSink        = (PBBHM_IP_PING_SINK_OBJECT     )pMyObject->hSinkObject;
    PANSC_XSOCKET_OBJECT            pSocket      = NULL;
    PDSLH_PING_INFO                 pDslhDiagInfo= (PDSLH_PING_INFO               )pMyObject->hDslhDiagInfo;
    PSINGLE_LINK_ENTRY              pSLinkEntry  = NULL;
    PBBHM_IP_PING_ECHO_ENTRY        pMEchoEntry  = NULL;
    SLIST_HEADER                    MiddleResult;
    ULONG                           i            = 0;
    ULONG                           MaxRetrieve  = 10;
    ULONG                           nRead        = 0;

    if ( pMyObject->bActive )
    {
        ULONG                       ulMin = 0;
        ULONG                       ulMax = 0;
        ULONG                       ulSum = 0;
        ULONG                       ulTime;

        pStateTimer->Stop((ANSC_HANDLE)pStateTimer);
        pStateTimer->SetStopTime((ANSC_HANDLE)pStateTimer, AnscGetTickInMilliSeconds());

        returnStatus =
            pMyObject->CalculateResult
                (
                    (ANSC_HANDLE)pMyObject
                );

        for (i = 0; i < MaxRetrieve; i++)
        {
            AnscAcquireLock(&pMyObject->MiddleResultLock);
            MiddleResult = pMyObject->MiddleResult;
            AnscReleaseLock(&pMyObject->MiddleResultLock);
            if (MiddleResult.Depth == 0)
            {
                break;
            }
            AnscSleep(100);
        }

        AnscAcquireLock(&pMyObject->MiddleResultLock);

        nRead = pMyObject->MiddleResult.Depth;
        pSLinkEntry = AnscSListPopEntry(&pMyObject->MiddleResult);
        while ( pSLinkEntry )
        {
            pMEchoEntry = (PBBHM_IP_PING_ECHO_ENTRY)ACCESS_BBHM_IP_PING_ECHO_ENTRY(pSLinkEntry);
            pSLinkEntry = AnscSListPopEntry(&pMyObject->MiddleResult);

            ulTime = pMEchoEntry->StopTime - pMEchoEntry->StartTime;

            /* calculate min, max, sum */
            if ( ulSum == 0 )
            {
                ulMin = ulMax = ulSum = ulTime;
            }
            else
            {
                if ( ulMin > ulTime )
                {
                    ulMin = ulTime;
                }

                if ( ulMax < ulTime )
                {
                    ulMax = ulTime;
                }

                ulSum += ulTime;
            }

            AnscFreeMemory(pMEchoEntry);
        }

        AnscReleaseLock(&pMyObject->MiddleResultLock);

        if ( nRead != 0 )
        {
            pProperty->AvgRTT   = ulSum/nRead;
            pProperty->MinRTT   = ulMin;
            pProperty->MaxRTT   = ulMax;
        }

        if ( pSink )
        {
            pSocket = (PANSC_XSOCKET_OBJECT             )pSink->GetXsocket((ANSC_HANDLE)pSink);
            pSocket->Close((ANSC_HANDLE)pSocket);
        }
    }

    switch ( pMyObject->GetStatus((ANSC_HANDLE)pMyObject) )
    {
        case  BBHM_IP_PING_STATUS_COMPLETE:

                pDslhDiagInfo->DiagnosticState = DSLH_DIAG_STATE_TYPE_Complete;

                break;

        case  BBHM_IP_PING_STATUS_ABORT:

                pDslhDiagInfo->DiagnosticState = DSLH_DIAG_STATE_TYPE_PING_Error_Internal;

                break;

        case  BBHM_IP_PING_STATUS_STOP:

                pDslhDiagInfo->DiagnosticState = DSLH_DIAG_STATE_TYPE_Complete;

                break;

        case  BBHM_IP_PING_STATUS_ERROR_HostName:

                pDslhDiagInfo->DiagnosticState = DSLH_DIAG_STATE_TYPE_Error_HostName;

                break;

        case  BBHM_IP_PING_STATUS_TIMEOUT:

                pMyObject->SetMaxRTT((ANSC_HANDLE)pMyObject, 0);
                pMyObject->SetMinRTT((ANSC_HANDLE)pMyObject, 0);
                pDslhDiagInfo->DiagnosticState = DSLH_DIAG_STATE_TYPE_Complete;

                break;

        default:

                return  returnStatus;
    }

    pMyObject->bResultQueryRunning     = FALSE;
    pDslhDiagInfo->SuccessCount        = nRead;
    pDslhDiagInfo->FailureCount        = pProperty->PktsSent - nRead;
    pDslhDiagInfo->AverageResponseTime = pProperty->AvgRTT;
    pDslhDiagInfo->MinimumResponseTime = pProperty->MinRTT;
    pDslhDiagInfo->MaximumResponseTime = pProperty->MaxRTT;

    return  returnStatus;
}
Exemplo n.º 12
0
ANSC_STATUS
AnscDetoRecvTask
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus  = ANSC_STATUS_SUCCESS;
    PANSC_DAEMON_ENGINE_TCP_OBJECT  pMyObject     = (PANSC_DAEMON_ENGINE_TCP_OBJECT)hThisObject;
    PANSC_DAEMON_SERVER_TCP_OBJECT  pServer       = (PANSC_DAEMON_SERVER_TCP_OBJECT)pMyObject->hDaemonServer;
    PANSC_DSTO_WORKER_OBJECT        pWorker       = (PANSC_DSTO_WORKER_OBJECT      )pServer->hWorker;
#if !defined(_ANSC_KERNEL) || !defined(_ANSC_LINUX)
    ansc_fd_set*                    pRecvSet1     = (ansc_fd_set*                  )pMyObject->RecvSocketSet;
    xskt_fd_set*                    pRecvSet2     = (xskt_fd_set*                  )pMyObject->RecvSocketSet;
#endif
    PANSC_DAEMON_SOCKET_TCP_OBJECT  pSocket       = NULL;
    ULONG                           ulLastCleanAt = AnscGetTickInSecondsAbs();
    ANSC_SOCKET                     s_socket      = ANSC_SOCKET_INVALID_SOCKET;
    int                             s_result      = 0;
    int                             s_result_excp = 0;
    int                             s_error       = 0;
    int                             i             = 0;
#if !defined(_ANSC_KERNEL) || !defined(_ANSC_LINUX)
    ansc_fd_set*                    read_fd_set1  = NULL;
    xskt_fd_set*                    read_fd_set2  = NULL;
    ansc_fd_set*                    excp_fd_set1  = NULL;
    xskt_fd_set*                    excp_fd_set2  = NULL;
    ansc_timeval                    timeval1;
    xskt_timeval                    timeval2;
#endif

    AnscTrace("AnscDetoRecvTask is activated ...!\n");

#if !defined(_ANSC_KERNEL) || !defined(_ANSC_LINUX)
    read_fd_set1 = (ansc_fd_set*)AnscAllocateMemory(sizeof(ansc_fd_set));
    read_fd_set2 = (xskt_fd_set*)AnscAllocateMemory(sizeof(xskt_fd_set));
    excp_fd_set1 = (ansc_fd_set*)AnscAllocateMemory(sizeof(ansc_fd_set));
    excp_fd_set2 = (xskt_fd_set*)AnscAllocateMemory(sizeof(xskt_fd_set));

    if ( !read_fd_set1 || !read_fd_set2 || !excp_fd_set1 || !excp_fd_set2 )
    {
        goto  EXIT1;
    }
#endif

    /*
     * As a scalable server implemention, we shall accept as many incoming client connections as
     * possible and can only be limited by the system resources. Once the listening socket becomes
     * readable, which means an incoming connection attempt has arrived. We create a new socket
     * object and associate it with the client. This is a repeated process until the socket owner
     * closes the socket.
     */
    while ( pMyObject->bStarted )
    {
        ANSC_COMMIT_TASK();

        /*
         * To avoid letting the old half-dead sockets hogging up the system resource, we need to
         * periodically invoke the cleaning routine. The default interval is 10 seconds, and the
         * idle timeout value is 90 seconds.
         */
	#if !defined(_ANSC_KERNEL) || !defined(_ANSC_LINUX)
        if ( pMyObject->bCleaningDemanded )
	#else
		if ( FALSE ) /*if ( pMyObject->bCleaningDemanded )*/
	#endif
        {
            pMyObject->Clean((ANSC_HANDLE)pMyObject);

            ulLastCleanAt                = AnscGetTickInSecondsAbs();
            pMyObject->bCleaningDemanded = FALSE;
        }
        else if ( (AnscGetTickInSecondsAbs() - ulLastCleanAt) >= ANSC_DETO_CLEAN_TASK_INTERVAL )
        {
            pMyObject->Clean((ANSC_HANDLE)pMyObject);

            ulLastCleanAt                = AnscGetTickInSecondsAbs();
            pMyObject->bCleaningDemanded = FALSE;
        }

        /*
         * Since the original bsd compatible socket api doesn't support asynchronous operation, the
         * nonblocking status polling is the best we can get. As a matter of fact, the current unix
         * and linux actually still don't support asynchronous notification on any socket operation.
         */
    #if defined(_ANSC_KERNEL) && defined(_ANSC_LINUX)
        if ( !pMyObject->CurSocketCount)
        {
            if ( pServer->Mode & ANSC_DSTO_MODE_EVENT_SYNC )
            {
                AnscWaitEvent (&pMyObject->NewSocketEvent, ANSC_DETO_WAIT_EVENT_INTERVAL);
                AnscResetEvent(&pMyObject->NewSocketEvent);

                if (!pMyObject->CurSocketCount)
                {
                    AnscTaskRelinquish();

                    continue;
                }
            }
            else
            {
                AnscSleep(ANSC_DETO_TASK_BREAK_INTERVAL);

                continue;
            }
        }
    #else
        if ( pServer->Mode & ANSC_DSTO_MODE_XSOCKET )
        {
            AnscAcquireLock(&pMyObject->RecvSocketSetLock);
            *read_fd_set2 = *pRecvSet2;
            AnscReleaseLock(&pMyObject->RecvSocketSetLock);
        }
        else
        {
            AnscAcquireLock(&pMyObject->RecvSocketSetLock);
            *read_fd_set1 = *pRecvSet1;
            AnscReleaseLock(&pMyObject->RecvSocketSetLock);
        }

        if ( ( (pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && XSKT_SOCKET_FD_ISNUL(read_fd_set2)) ||
             (!(pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && ANSC_SOCKET_FD_ISNUL(read_fd_set1)) )
        {
            if ( pServer->Mode & ANSC_DSTO_MODE_EVENT_SYNC )
            {
                AnscWaitEvent (&pMyObject->NewSocketEvent, ANSC_DETO_WAIT_EVENT_INTERVAL);
                AnscResetEvent(&pMyObject->NewSocketEvent);

                if ( pServer->Mode & ANSC_DSTO_MODE_XSOCKET )
                {
                    AnscAcquireLock(&pMyObject->RecvSocketSetLock);
                    *read_fd_set2 = *pRecvSet2;
                    AnscReleaseLock(&pMyObject->RecvSocketSetLock);
                }
                else
                {
                    AnscAcquireLock(&pMyObject->RecvSocketSetLock);
                    *read_fd_set1 = *pRecvSet1;
                    AnscReleaseLock(&pMyObject->RecvSocketSetLock);
                }

                if ( ( (pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && XSKT_SOCKET_FD_ISNUL(read_fd_set2)) ||
                     (!(pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && ANSC_SOCKET_FD_ISNUL(read_fd_set1)) )
                {
                    AnscTaskRelinquish();

                    continue;
                }
            }
            else
            {
                AnscSleep(ANSC_DETO_TASK_BREAK_INTERVAL);

                continue;
            }
        }

        if ( pServer->Mode & ANSC_DSTO_MODE_XSOCKET )
        {
            timeval2.tv_sec  = (ANSC_DETO_POLL_INTERVAL_MS / 1000);          /* number of seconds      */
            timeval2.tv_usec = (ANSC_DETO_POLL_INTERVAL_MS % 1000) * 1000;   /* number of microseconds */
        }
        else
        {
            timeval1.tv_sec  = (ANSC_DETO_POLL_INTERVAL_MS / 1000);          /* number of seconds      */
            timeval1.tv_usec = (ANSC_DETO_POLL_INTERVAL_MS % 1000) * 1000;   /* number of microseconds */
        }

        /*
         * The _ansc_select() function returns the total number of socket handles that are ready
         * and contained in the fd_set structures, zero if the time limit expired, or SOCKET_ERROR
         * if an error occurred. Upon return, the structures are updated to reflect the subset of
         * these sockets that meet the specified condition.
         */
        if ( pServer->Mode & ANSC_DSTO_MODE_XSOCKET )
        {
            s_result = _xskt_select(XSKT_SOCKET_FD_SETSIZE, read_fd_set2, NULL, NULL, &timeval2);
        }
        else
        {
            s_result = _ansc_select(ANSC_SOCKET_FD_SETSIZE, read_fd_set1, NULL, NULL, &timeval1);
        }

        if ( s_result == 0 )
        {
            continue;
        }
        else if ( ( (pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && (s_result == XSKT_SOCKET_ERROR)) ||
                  (!(pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && (s_result == ANSC_SOCKET_ERROR)) )
        {
            s_error = (pServer->Mode & ANSC_DSTO_MODE_XSOCKET)? _xskt_get_last_error() : _ansc_get_last_error();

            /*
             * Previously we simply reset everything when _ansc_select() fails, which is not a good
             * solution: we shall notify the worker module and gracefully shutdown the socket(s)
             * that caused the error.
             */
            /*
            pMyObject->Reset((ANSC_HANDLE)pMyObject);
            */
            pMyObject->ExpAllSockets((ANSC_HANDLE)pMyObject);

            continue;
        }
        else if ( !pMyObject->bStarted )
        {
            break;
        }
	#endif

        /*
         * If there're multiple sockets are receiving data, we loop through the returned fd_set
         * structure and process them one-by-one. However, we have a slight problem: the resulted
         * fd_set consists of only the native socket handles, not the associated Socket Objects.
         * We have to first retrieve the peer's IP address from the socket, and use it to find
         * the associated socket object.
         */
	#if defined(_ANSC_KERNEL) && defined(_ANSC_LINUX)
        if (TRUE)
        {
            int                             i; 
            PSINGLE_LINK_ENTRY              pSLinkEntry;

            for ( i = 0; i < ANSC_DETO_SOCKET_TABLE_SIZE ; i++)
            {
                if (!AnscSListQueryDepth(&pMyObject->SocketTable[i]))
                {
                    continue;
                }

                AnscAcquireLock(&pMyObject->SocketTableLock);

                pSLinkEntry = AnscSListGetFirstEntry(&pMyObject->SocketTable[i]);

                AnscReleaseLock(&pMyObject->SocketTableLock);

                while ( pSLinkEntry )
                {
                    pSocket     = ACCESS_ANSC_DAEMON_SOCKET_TCP_OBJECT(pSLinkEntry);
                    pSLinkEntry = AnscSListGetNextEntry(pSLinkEntry);

					if ( pSocket->bTlsEnabled )
					{
                        pMyObject->bBusy = TRUE;

                        returnStatus =
                            pMyObject->Recv2
                                (
                                    (ANSC_HANDLE)pMyObject,
                                    (ANSC_HANDLE)pSocket
                                );

                        pMyObject->bBusy = FALSE;
					}
                    else
                    {
                        pMyObject->bBusy = TRUE;

						returnStatus =
							pMyObject->Recv
								(
									(ANSC_HANDLE)pMyObject,
									(ANSC_HANDLE)pSocket
								);

                        pMyObject->bBusy = FALSE;
                    }
                }

                if ( !pMyObject->bStarted )
                {
                    break;
                }
            }

            AnscSleep(10);
        }
	#else
        for ( i = 0; i < s_result; i++ )
        {
            if ( pServer->Mode & ANSC_DSTO_MODE_XSOCKET )
            {
                XSKT_SOCKET_FD_GET(read_fd_set2, s_socket, (ULONG)i);
            }
            else
            {
                ANSC_SOCKET_FD_GET(read_fd_set1, s_socket, (ULONG)i);
            }

            if ( ( (pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && (s_socket == XSKT_SOCKET_INVALID_SOCKET)) ||
                 (!(pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && (s_socket == ANSC_SOCKET_INVALID_SOCKET)) )
            {
                break;
            }
            else
            {
                pSocket =
                    (PANSC_DAEMON_SOCKET_TCP_OBJECT)pMyObject->GetSocketByOsocket
                        (
                            (ANSC_HANDLE)pMyObject,
                            s_socket
                        );
                /*
                 * We should make sure this socket is still valid before proceeding with the socket
                 * receive operations. For example, the peer may have already closed or reset the
                 * TCP connection while we're serving the previous socket request.
                 *
                 * 10/06/04 - It's believed this modification is slowing down the GUI and we're not
                 * seeing tangible evidence that GUI responsivenss has been improved. So we disable
                 * it for now.
                 */
                /*
                if ( pServer->Mode & ANSC_DSTO_MODE_XSOCKET )
                {
                    XSKT_SOCKET_FD_ZERO(excp_fd_set2);
                    XSKT_SOCKET_FD_SET ((XSKT_SOCKET)s_socket, excp_fd_set2);

                    timeval2.tv_sec  = 0;
                    timeval2.tv_usec = 0;

                    s_result_excp = _xskt_select(XSKT_SOCKET_FD_SETSIZE, NULL, NULL, excp_fd_set2, &timeval2);
                }
                else
                {
                    ANSC_SOCKET_FD_ZERO(excp_fd_set1);
                    ANSC_SOCKET_FD_SET (s_socket, excp_fd_set1);

                    timeval1.tv_sec  = 0;
                    timeval1.tv_usec = 0;

                    s_result_excp = _ansc_select(ANSC_SOCKET_FD_SETSIZE, NULL, NULL, excp_fd_set1, &timeval1);
                }
                */
            }

            /*
            if ( ((s_result_excp == 1                )                                             ) ||
                 ((s_result_excp == XSKT_SOCKET_ERROR) &&  (pServer->Mode & ANSC_DSTO_MODE_XSOCKET)) ||
                 ((s_result_excp == ANSC_SOCKET_ERROR) && !(pServer->Mode & ANSC_DSTO_MODE_XSOCKET)) )
            {
                if ( TRUE )
                {
                    pSocket->bBroken = TRUE;

                    pMyObject->EnableRecv((ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket, FALSE);
                    pMyObject->EnableSend((ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket, FALSE);
                }

                if ( pSocket->bTlsEnabled )
                {
                    if ( pSocket->bTlsEnabled && pSocket->bTlsConnected && !pSocket->bTlsInitializing )
                    {
                        returnStatus =
                            pWorker->Notify
                                (
                                    pWorker->hWorkerContext,
                                    (ANSC_HANDLE)pSocket,
                                    ANSC_DSTOWO_EVENT_SOCKET_ERROR,
                                    (ANSC_HANDLE)NULL
                                );
                    }
                    else
                    {
                        AnscSetEvent(&pSocket->TlsConnEvent);
                    }
                }
                else
                {
                    returnStatus =
                        pWorker->Notify
                            (
                                pWorker->hWorkerContext,
                                (ANSC_HANDLE)pSocket,
                                ANSC_DSTOWO_EVENT_SOCKET_ERROR,
                                (ANSC_HANDLE)NULL
                            );
                }

                if ( pServer->Mode & ANSC_DSTO_MODE_AUTO_CLOSE )
                {
                    pMyObject->DelSocket((ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket);
                }

                pMyObject->TrcCount++;

                continue;
            }
            else
            {
                pSocket =
                    (PANSC_DAEMON_SOCKET_TCP_OBJECT)pMyObject->GetSocketByOsocket
                        (
                            (ANSC_HANDLE)pMyObject,
                            s_socket
                        );
            }
            */

            if ( !pSocket )
            {
                continue;
            }
            else if ( pSocket->bTlsEnabled )
            {
#ifdef _ANSC_USE_OPENSSL_
                pMyObject->bBusy = TRUE;

                returnStatus =
                    pMyObject->Recv
                        (
                            (ANSC_HANDLE)pMyObject,
                            (ANSC_HANDLE)pSocket
                        );

                pMyObject->bBusy = FALSE;
#else
                pMyObject->bBusy = TRUE;

                returnStatus =
                    pMyObject->Recv2
                        (
                            (ANSC_HANDLE)pMyObject,
                            (ANSC_HANDLE)pSocket
                        );

                pMyObject->bBusy = FALSE;
#endif
            }
            else
            {
                pMyObject->bBusy = TRUE;

                returnStatus =
                    pMyObject->Recv
                        (
                            (ANSC_HANDLE)pMyObject,
                            (ANSC_HANDLE)pSocket
                        );

                pMyObject->bBusy = FALSE;
            }

            /*
             * Check whether 'bToBeCleaned' flag is set for this socket: if it is, we should close
             * this socket right away; otherwise, we continue the processing. WARNING!!! This new
             * change seems to incur instability in SLAP, we have to roll back to the initial
             * approach.
             */
            /*
            if ( pSocket->bToBeCleaned )
            {
                returnStatus =
                    pMyObject->DelSocket
                        (
                            (ANSC_HANDLE)pMyObject,
                            (ANSC_HANDLE)pSocket
                        );
            }
            */

            if ( !pMyObject->bStarted )
            {
                break;
            }
        }
	#endif
    }


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

EXIT1:

    AnscSetEvent(&pMyObject->RecvEvent);

#if !defined(_ANSC_KERNEL) || !defined(_ANSC_LINUX)
    if ( read_fd_set1 )
    {
        AnscFreeMemory(read_fd_set1);
    }

    if ( read_fd_set2 )
    {
        AnscFreeMemory(read_fd_set2);
    }

    if ( excp_fd_set1 )
    {
        AnscFreeMemory(excp_fd_set1);
    }

    if ( excp_fd_set2 )
    {
        AnscFreeMemory(excp_fd_set2);
    }
#endif

    return  ANSC_STATUS_SUCCESS;
}
Exemplo n.º 13
0
ANSC_STATUS
AnscBetoRecvTask
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus  = ANSC_STATUS_SUCCESS;
    PANSC_BROKER_ENGINE_TCP_OBJECT  pMyObject     = (PANSC_BROKER_ENGINE_TCP_OBJECT)hThisObject;
    PANSC_BROKER_SERVER_TCP_OBJECT  pServer       = (PANSC_BROKER_SERVER_TCP_OBJECT)pMyObject->hBrokerServer;
    ansc_fd_set*                    pRecvSet1     = (ansc_fd_set*                  )pMyObject->RecvSocketSet;
    xskt_fd_set*                    pRecvSet2     = (xskt_fd_set*                  )pMyObject->RecvSocketSet;
    PANSC_BROKER_SOCKET_TCP_OBJECT  pSocket       = NULL;
    ULONG                           ulLastCleanAt = AnscGetTickInSeconds();
    ANSC_SOCKET                     s_socket      = ANSC_SOCKET_INVALID_SOCKET;
    int                             s_result      = 0;
    int                             s_result_excp = 0;
    int                             s_error       = 0;
    int                             i             = 0;
    uni_fd_set                      read_fd_set;
    /*uni_fd_set                      excp_fd_set;*/
    uni_timeval                     timeval;

    AnscTrace("AnscBetoRecvTask is activated ...!\n");

    /*
     * As a scalable server implemention, we shall accept as many incoming client connections as
     * possible and can only be limited by the system resources. Once the listening socket becomes
     * readable, which means an incoming connection attempt has arrived. We create a new socket
     * object and associate it with the client. This is a repeated process until the socket owner
     * closes the socket.
     */
    while ( pMyObject->bStarted )
    {
        ANSC_COMMIT_TASK();

        /*
         * To avoid letting the old half-dead sockets hogging up the system resource, we need to
         * periodically invoke the cleaning routine. The default interval is 10 seconds, and the
         * idle timeout value is 90 seconds.
         */
        if ( pMyObject->bCleaningDemanded  || 
             (AnscGetTickInSeconds() - ulLastCleanAt) >= ANSC_BETO_CLEAN_TASK_INTERVAL )
        {
            pMyObject->Clean((ANSC_HANDLE)pMyObject);

            ulLastCleanAt                = AnscGetTickInSeconds();
            pMyObject->bCleaningDemanded = FALSE;
        }

        /*
         * The _ansc_select() function returns the total number of socket handles that are ready
         * and contained in the fd_set structures, zero if the time limit expired, or SOCKET_ERROR
         * if an error occurred. Upon return, the structures are updated to reflect the subset of
         * these sockets that meet the specified condition.
         */
    
        if ( pServer->Mode & ANSC_BSTO_MODE_XSOCKET )
        {
            /*
             * no need to use lock for read_fd_set here, dirty read does not matter.
             */
            read_fd_set.xset = *pRecvSet2;

            if( XSKT_SOCKET_FD_ISNUL(&read_fd_set.xset) )
            {
                if ( pServer->Mode & ANSC_BSTO_MODE_EVENT_SYNC )
                {
                    AnscWaitEvent (&pMyObject->NewSocketEvent, ANSC_BETO_WAIT_EVENT_INTERVAL);
                    AnscResetEvent(&pMyObject->NewSocketEvent);
                }
                else
                {
                    AnscSleep(ANSC_BETO_TASK_BREAK_INTERVAL);
                }

                continue;
            }

            timeval.xtv.tv_sec  = (ANSC_BETO_POLL_INTERVAL_MS / 1000);          /* number of seconds      */
            timeval.xtv.tv_usec = (ANSC_BETO_POLL_INTERVAL_MS % 1000) * 1000;   /* number of microseconds */

            s_result = _xskt_select(XSKT_SOCKET_FD_SETSIZE, &read_fd_set.xset, NULL, NULL, &timeval.xtv);

            if ( s_result == 0 )
            {
                continue;
            }

            if ( s_result == XSKT_SOCKET_ERROR )
            {
                s_error = _xskt_get_last_error();
                pMyObject->Reset((ANSC_HANDLE)pMyObject);
                continue;
            }
            
        }
        else
        {
            /*
             * no need to use lock for read_fd_set here, dirty read does not matter.
             */
            read_fd_set.aset = *pRecvSet1;

            if( ANSC_SOCKET_FD_ISNUL(&read_fd_set.aset) )
            {

                if ( pServer->Mode & ANSC_BSTO_MODE_EVENT_SYNC )
                {
                    AnscWaitEvent (&pMyObject->NewSocketEvent, ANSC_BETO_WAIT_EVENT_INTERVAL);
                    AnscResetEvent(&pMyObject->NewSocketEvent);
                }
                else
                {
                    AnscSleep(ANSC_BETO_TASK_BREAK_INTERVAL);
                }

                continue;
            }

            timeval.atv.tv_sec  = (ANSC_BETO_POLL_INTERVAL_MS / 1000);          /* number of seconds      */
            timeval.atv.tv_usec = (ANSC_BETO_POLL_INTERVAL_MS % 1000) * 1000;   /* number of microseconds */

            s_result = _ansc_select(ANSC_SOCKET_FD_SETSIZE, &read_fd_set.aset, NULL, NULL, &timeval.atv);

            if ( s_result == 0 )
            {
                continue;
            }

            if ( s_result == ANSC_SOCKET_ERROR )
            {
                s_error = _ansc_get_last_error();
                pMyObject->Reset((ANSC_HANDLE)pMyObject);
                continue;
            }
            
        }

        /*
         * If there're multiple sockets are receiving data, we loop through the returned fd_set
         * structure and process them one-by-one. However, we have a slight problem: the resulted
         * fd_set consists of only the native socket handles, not the associated Socket Objects.
         * We have to first retrieve the peer's IP address from the socket, and use it to find
         * the associated socket object.
         */
        for ( i = 0; i < s_result; i++ )
        {
            if ( !pMyObject->bStarted )
            {
                break;
            }

            if ( pServer->Mode & ANSC_BSTO_MODE_XSOCKET )
            {
                XSKT_SOCKET_FD_GET(&read_fd_set.xset, s_socket, (ULONG)i);
                if( s_socket == XSKT_SOCKET_INVALID_SOCKET )
                {
                    break;
                }

                if( ! XSKT_SOCKET_FD_ISSET(s_socket, pRecvSet2) )
                {
                    AnscTraceError(("AnscBetoRecvTask: XSKT_SOCKET_FD_ISSET returned FALSE.\n"));
                    continue;
                }
            }
            else
            {
                ANSC_SOCKET_FD_GET(&read_fd_set.aset, s_socket, (ULONG)i);
                if( s_socket == ANSC_SOCKET_INVALID_SOCKET )
                {
                    break;
                }

                if( ! ANSC_SOCKET_FD_ISSET(s_socket, pRecvSet1) )
                {
                    AnscTraceError(("AnscBetoRecvTask: XSKT_SOCKET_FD_ISSET returned FALSE.\n"));
                    continue;
                }
            }

            pSocket =
                (PANSC_BROKER_SOCKET_TCP_OBJECT)pMyObject->GetSocketByOsocket
                    (
                        (ANSC_HANDLE)pMyObject,
                        s_socket
                    );
 
            if ( !pSocket )
            {
                continue;
            }

            /*
             * We should make sure this socket is still valid before proceeding with the socket
             * receive operations. For example, the peer may have already closed or reset the
             * TCP connection while we're serving the previous socket request.
             *
             * 10/06/04 - It's believed this modification is slowing down the GUI and we're not
             * seeing tangible evidence that GUI responsivenss has been improved. So we disable
             * it for now.
             *
             * 11/20/09 - Re-activate the following code segment to validate the socket before
             * proceeding.
             */
            /*
            if ( pServer->Mode & ANSC_BSTO_MODE_XSOCKET )
            {
                XSKT_SOCKET_FD_ZERO((&excp_fd_set.xset));
                XSKT_SOCKET_FD_SET ((XSKT_SOCKET)s_socket, (&excp_fd_set.xset));

                timeval.xtv.tv_sec  = 0;
                timeval.xtv.tv_usec = 0;

                s_result_excp = _xskt_select(XSKT_SOCKET_FD_SETSIZE, NULL, NULL, &excp_fd_set.xset, &timeval.xtv);
            }
            else
            {
                ANSC_SOCKET_FD_ZERO((&excp_fd_set.aset));
                ANSC_SOCKET_FD_SET (s_socket, (&excp_fd_set.aset));

                timeval.atv.tv_sec  = 0;
                timeval.atv.tv_usec = 0;

                s_result_excp = _ansc_select(ANSC_SOCKET_FD_SETSIZE, NULL, NULL, &excp_fd_set.aset, &timeval.atv);
            }

            if ( ((s_result_excp == 1                )                                             ) ||
                 ((s_result_excp == XSKT_SOCKET_ERROR) &&  (pServer->Mode & ANSC_BSTO_MODE_XSOCKET)) ||
                 ((s_result_excp == ANSC_SOCKET_ERROR) && !(pServer->Mode & ANSC_BSTO_MODE_XSOCKET)) )
            {
                if ( TRUE )
                {
                    pSocket->bBroken      = TRUE;
                    pSocket->bToBeCleaned = TRUE;

                    pMyObject->EnableRecv((ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket, FALSE);
                    pMyObject->EnableSend((ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket, FALSE);
                }

                if ( pServer->Mode & ANSC_BSTO_MODE_AUTO_CLOSE )
                {
                    pMyObject->DelSocket((ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket);
                }

                continue;
            }
            */

            returnStatus = 
                pMyObject->Recv
                    (
                        (ANSC_HANDLE)pMyObject,
                        (ANSC_HANDLE)pSocket
                    );
 
        }
    }

    AnscSetEvent(&pMyObject->RecvEvent);

    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
}