ANSC_STATUS
BbhmDiagipExpire2
    (
        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;

    pMyObject->SetStatus((ANSC_HANDLE)pMyObject, BBHM_IP_PING_STATUS_TIMEOUT);
    pMyObject->Stop((ANSC_HANDLE)pMyObject);

    return  returnStatus;
}
ANSC_STATUS
BbhmDiagipRecv
    (
        ANSC_HANDLE                 hThisObject,
        ANSC_HANDLE                 hSinkObject,
        PVOID                       buffer,
        ULONG                       ulSize
    )
{
    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     )hSinkObject;
    PANSC_XSOCKET_OBJECT            pSocket      = (PANSC_XSOCKET_OBJECT          )pSink->GetXsocket((ANSC_HANDLE)pSink);
    PIPV4_HEADER                    pIpv4Header  = (PIPV4_HEADER                  )NULL;
    /*PIPV6_HEADER                    pIpv6Header  = (PIPV6_HEADER                  )NULL;*/
    PICMPV4_ECHO_MESSAGE            pIcmpHeader  = (PICMPV4_ECHO_MESSAGE          )NULL;
    PBBHM_IP_PING_ECHO_ENTRY        pMEchoEntry  = NULL;
    ULONG                           StopTime     = 0;

    StopTime = AnscGetTickInMilliSeconds();

    if ( pProperty->Status != BBHM_IP_PING_STATUS_RUNNING )
    {
        return  ANSC_STATUS_UNAPPLICABLE;
    }

    if ( pMyObject->IPProtocol == XSKT_SOCKET_AF_INET )
    {
        pIpv4Header = (PIPV4_HEADER)buffer;
        pIcmpHeader = (PICMPV4_ECHO_MESSAGE)AnscIpv4GetPayload(pIpv4Header);

        if ( ! AnscEqualString(pSocket->PeerName, pProperty->pDstAddrName, TRUE)/*(pSocket->PeerAddress.Value != pProperty->DstIp.Value)*/
            || (AnscIcmpv4EchoGetId(pIcmpHeader) !=  tempId) )
        {
            return  ANSC_STATUS_FAILURE;
        }

        if ( (AnscIcmpv4EchoGetType(pIcmpHeader) == ICMP_TYPE_DESTINATION_UNREACHABLE)
            || (AnscIcmpv4EchoGetType(pIcmpHeader) == ICMP_TYPE_TIME_EXCEEDED)
            || (AnscIcmpv4EchoGetType(pIcmpHeader) == ICMP_TYPE_PARAMETER_PROBLEM)
            || (AnscIcmpv4EchoGetType(pIcmpHeader) == ICMP_TYPE_SOURCE_QUENCH)
            || (AnscIcmpv4EchoGetType(pIcmpHeader) == ICMP_TYPE_REDIRECT))
        {
            pProperty->NumIcmpError ++;
            pProperty->IcmpError = AnscIcmpv4EchoGetType(pIcmpHeader);

            pMEchoEntry = (PBBHM_IP_PING_ECHO_ENTRY)AnscAllocateMemory(sizeof(BBHM_IP_PING_ECHO_ENTRY));
            if ( pMEchoEntry )
            {
                pMEchoEntry->ICMPType = AnscIcmpv4EchoGetType(pIcmpHeader);
                AnscAcquireLock(&pMyObject->MiddleResultLock);
                AnscSListPushEntryAtBack(&pMyObject->MiddleResult, &pMEchoEntry->Linkage);
                AnscReleaseLock(&pMyObject->MiddleResultLock);
            }

            return  ANSC_STATUS_FAILURE;
        }

        returnStatus =
            pMyObject->SetStopTime
                (
                    (ANSC_HANDLE)pMyObject,
                    AnscIcmpv4EchoGetSeqNumber(pIcmpHeader),
                    AnscIpv4GetTotalLength(pIpv4Header) - sizeof(IPV4_HEADER) - sizeof(ICMPV4_HEADER),
                    AnscIpv4GetTtl(pIpv4Header),
                    StopTime
                );
    }
    else if ( pMyObject->IPProtocol == XSKT_SOCKET_AF_INET6 )
    {
        pIcmpHeader = (PICMPV6_ECHO_MESSAGE)buffer;

        if ( ! AnscEqualString(pSocket->PeerName, pProperty->pDstAddrName, TRUE)/*(pSocket->PeerAddress.Value != pProperty->DstIp.Value)*/
            || (AnscIcmpv6EchoGetId(pIcmpHeader) !=  tempId) )
        {
            return  ANSC_STATUS_FAILURE;
        }

        if ( (AnscIcmpv6EchoGetType(pIcmpHeader) == ICMP6_TYPE_DESTINATION_UNREACHABLE)
            || (AnscIcmpv6EchoGetType(pIcmpHeader) == ICMP6_TYPE_TIME_EXCEEDED)
            || (AnscIcmpv6EchoGetType(pIcmpHeader) == ICMP6_TYPE_PARAMETER_PROBLEM)
            || (AnscIcmpv6EchoGetType(pIcmpHeader) == ICMP6_TYPE_PACKET_TOO_BIG))
        {
            pProperty->NumIcmpError ++;
            pProperty->IcmpError = AnscIcmpv6EchoGetType(pIcmpHeader);

            pMEchoEntry = (PBBHM_IP_PING_ECHO_ENTRY)AnscAllocateMemory(sizeof(BBHM_IP_PING_ECHO_ENTRY));
            if ( pMEchoEntry )
            {
                pMEchoEntry->ICMPType = AnscIcmpv6EchoGetType(pIcmpHeader);
                AnscAcquireLock(&pMyObject->MiddleResultLock);
                AnscSListPushEntryAtBack(&pMyObject->MiddleResult, &pMEchoEntry->Linkage);
                AnscReleaseLock(&pMyObject->MiddleResultLock);
            }

            return  ANSC_STATUS_FAILURE;
        }

        returnStatus =
            pMyObject->SetStopTime
                (
                    (ANSC_HANDLE)pMyObject,
                    AnscIcmpv6EchoGetSeqNumber(pIcmpHeader),
                    ulSize,
                    0,           /* Hop Limit */
                    StopTime
                );
    }

    if ( returnStatus == ANSC_STATUS_SUCCESS )
    {
        pProperty->PktsRecv ++;
    }

    if ( pProperty->PktsRecv == pProperty->NumPkts )
    {
        pMyObject->SetStatus((ANSC_HANDLE)pMyObject, BBHM_IP_PING_STATUS_COMPLETE);
        pMyObject->Stop((ANSC_HANDLE)pMyObject);
    }

    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;

}