PingSocket.cpp
Upload User: dzyhzl
Upload Date: 2019-04-29
Package Size: 56270k
Code Size: 7k
Development Platform:

C/C++

  1. ////////////////////////////////////////////////////////////////////////////////
  2. //  
  3. //  FileName    :   PingSocket.cpp
  4. //  Version     :   1.0
  5. //  Creater     :   Linsuyi
  6. //  Date        :   2002-01-10  09:21:42
  7. //  Comment     :   Tcp/ip ping socket source file
  8. //  
  9. ////////////////////////////////////////////////////////////////////////////////
  10. #include "Stdafx.h"
  11. #include "PingSocket.h"
  12. //////////////////////////////////////////////////////////////////////
  13. // Construction/Destruction
  14. //////////////////////////////////////////////////////////////////////
  15. CPingSocket::CPingSocket()
  16.   : CRawSocket()
  17. {
  18.     m_nSckProto = IPPROTO_ICMP;
  19.     
  20.     m_nLastSequence = DEFAULT_PING_SEQUENCE;
  21.     m_nLastPingTime = -1;
  22. }
  23. CPingSocket::~CPingSocket()
  24. {
  25. }
  26. int CPingSocket::Create()
  27. {
  28.     CRawSocket::SetBlockMode(false);
  29.     
  30.     return CRawSocket::Create();
  31. }
  32. int CPingSocket::PingToAddress(const char *pcszRemoteAddr, int& nTimeOut)
  33. {
  34.     int nResult = false;
  35.     int nRetCode = true;
  36.     
  37.     INET_ADDRESS saRemoteAddr = { 0 };
  38.     
  39.     ASSERT(pcszRemoteAddr);
  40.     if (NULL == pcszRemoteAddr)
  41.         goto Exit0;
  42.     
  43.     nRetCode = CRawSocket::GetSocketAddress(pcszRemoteAddr, &saRemoteAddr);
  44.     if (!nRetCode)
  45.     {
  46.         DoEventNotify(PINGEVENT_HOSTNOTFOUND);
  47.         goto Exit0;
  48.     }
  49.     
  50.     nResult = PingToAddress(&saRemoteAddr, nTimeOut);
  51.     
  52. Exit0:
  53.     return nResult;
  54. }
  55. int CPingSocket::PingToAddress(const INET_ADDRESS *psaRemoteAddr, int& nTimeOut)
  56. {
  57.     int nResult = PINGRESULT_TESTBREAK;
  58.     int nRetCode = 0;
  59.     
  60.     int nIsBreak = false;
  61.     int nTimeLeft = nTimeOut;
  62.     ULONG ulTimeStart = 0;
  63.     
  64.     int nSendSize = 0;
  65.     int nRecvSize = 0;
  66.     unsigned char *pSendBuf = NULL;
  67.     unsigned char *pRecvBuf = NULL;
  68.     
  69.     PING_ECHOREQUEST EchoRequest = { 0 };
  70.     PING_ECHOREPLY   EchoReply   = { 0 };
  71.     
  72.     if (!IsSocketOK())
  73.     {
  74.         ASSERT(FALSE);
  75.         
  76.         nResult = PINGRESULT_OCCURERROR;
  77.         goto Exit0;
  78.     }
  79.     
  80.     nRetCode = DoEventNotify(PINGEVENT_TESTBREAK);
  81.     if (nRetCode)
  82.     {
  83.         nIsBreak = true;
  84.         goto Exit0;
  85.     }
  86.     
  87.     nRetCode = CRawSocket::SetRemoteAddress(psaRemoteAddr);
  88.     if (!nRetCode)
  89.     {
  90.         nResult = PINGRESULT_OCCURERROR;
  91.         goto Exit0;
  92.     }
  93.     
  94.     EchoRequest.icmpHdr.ID  = DEFAULT_PING_ID;
  95.     EchoRequest.icmpHdr.Seq = ++m_nLastSequence;
  96.     EchoRequest.unSignMain  = DEFAULT_PING_SIGN_MAIN;
  97.     EchoRequest.unSignExt   = (unsigned int)CRawSocket::GetSafeHandle();
  98.     EchoRequest.unTimeMain  = ::GetTickCount();    
  99.     
  100.     nSendSize = sizeof(PING_ECHOREQUEST);
  101.     pSendBuf  = (unsigned char *)&EchoRequest;
  102.     nRetCode  = OnPingDataSend(&nSendSize, &pSendBuf);
  103.     ASSERT(nRetCode ? ((nSendSize > 0) && (pSendBuf != NULL)) : TRUE);
  104.     if (!nRetCode)
  105.     {
  106.         nResult = PINGRESULT_OCCURERROR;
  107.         goto Exit0;
  108.     }
  109.     
  110.     EchoRequest.icmpHdr.Type     = ICMPTYPE_ECHOREQUEST;
  111.     EchoRequest.icmpHdr.Code     = 0;
  112.     
  113.     nRetCode = DoEventNotify(PINGEVENT_TESTBREAK);
  114.     if (nRetCode)
  115.     {
  116.         nIsBreak = true;
  117.         goto Exit0;
  118.     }
  119.     
  120.     nRecvSize = sizeof(PING_ECHOREPLY);
  121.     pRecvBuf  = (unsigned char *)&EchoReply;
  122.     nRetCode = OnPingDataReceive(&nRecvSize, &pRecvBuf);
  123.     ASSERT(nRetCode ? ((nRecvSize > 0) && (pRecvBuf != NULL)) : TRUE);
  124.     if (!nRetCode)
  125.     {
  126.         nResult = PINGRESULT_OCCURERROR;
  127.         goto Exit0;
  128.     }
  129.     
  130.     EchoRequest.icmpHdr.Checksum = 0;
  131.     EchoRequest.icmpHdr.Checksum = inet_chksum((unsigned short *)pSendBuf, nSendSize);
  132.     
  133.     ulTimeStart = ::GetTickCount();
  134.     nRetCode = SendTo(nSendSize, pSendBuf);
  135.     if (SOCKET_ERROR == nRetCode)
  136.     {
  137.         nResult = PINGRESULT_OCCURERROR;
  138.         goto Exit0;
  139.     }
  140.     
  141.     while (nTimeLeft > 0)
  142.     {
  143.         nRetCode = CRawSocket::Select(true, false, false, nTimeLeft);
  144.         if (0 == nRetCode)
  145.         {
  146.             nTimeOut = (int)(::GetTickCount() - ulTimeStart);
  147.             nResult = PINGRESULT_TIMEOUT;
  148.             goto Exit0;
  149.         }
  150.         else if (SOCKET_ERROR == nRetCode)
  151.         {
  152.             nResult = PINGRESULT_OCCURERROR;
  153.             goto Exit0;
  154.         }
  155.         
  156.         nRetCode = CRawSocket::ReceiveFrom(nRecvSize, pRecvBuf);
  157.         nTimeLeft -= (int)(::GetTickCount() - ulTimeStart);
  158.         
  159.         if (
  160.             (nRetCode >= (sizeof(IPHDR) + sizeof(ICMPHDR))) && 
  161.             (EchoReply.echoRequest.icmpHdr.ID == EchoRequest.icmpHdr.ID) && 
  162.             (EchoReply.echoRequest.icmpHdr.Seq  == EchoRequest.icmpHdr.Seq) && 
  163.             (EchoReply.echoRequest.icmpHdr.Code == EchoRequest.icmpHdr.Code)
  164.         )
  165.         {
  166.             // Cannot receive this package as this routine use point-to-point ICMP
  167.             if (ICMPTYPE_DSTNOTTOUCH == EchoReply.echoRequest.icmpHdr.Type)
  168.             {
  169.                 DoEventNotify(PINGEVENT_HOSTNOTFOUND);
  170.                 
  171.                 nResult = PINGEVENT_HOSTNOTFOUND;
  172.                 goto Exit0;
  173.             }
  174.             
  175.             if (
  176.                 (nRetCode >= (sizeof(IPHDR) + sizeof(PING_ECHOREQUEST))) && 
  177.                 (ICMPTYPE_ECHOREPLY == EchoReply.echoRequest.icmpHdr.Type) && 
  178.                 (EchoReply.echoRequest.unSignMain == EchoRequest.unSignMain) && 
  179.                 (EchoReply.echoRequest.unSignExt  == EchoRequest.unSignExt )
  180.             )
  181.             {
  182.                 break;
  183.             }
  184.         }
  185.         
  186.         nRetCode = DoEventNotify(PINGEVENT_REPEAT);
  187.         if (!nRetCode)
  188.         {
  189.             nResult = PINGRESULT_OCCURERROR;
  190.             goto Exit0;
  191.         }
  192.         
  193.         nRetCode = DoEventNotify(PINGEVENT_TESTBREAK);
  194.         if (nRetCode)
  195.             goto Exit0;
  196.     }
  197.     
  198.     nTimeOut -= nTimeLeft;
  199.     if (nTimeOut < 0)
  200.     {
  201.         ASSERT(FALSE);
  202.         
  203.         nTimeOut = 0;
  204.     }
  205.     
  206.     m_nLastPingTime = nTimeOut;
  207.     
  208.     nResult = PINGRESULT_SUCCESS;
  209.     
  210. Exit0:
  211.     if (nResult != PINGRESULT_SUCCESS)
  212.     {
  213.     }
  214.     
  215.     return nResult;
  216. }
  217. int CPingSocket::GetLastPingTime()
  218. {
  219.     return m_nLastPingTime;
  220. }
  221. int CPingSocket::OnPingDataSend(int *pnBufSize, unsigned char **ppbyDataSend)
  222. {
  223.     return true;
  224. }
  225. int CPingSocket::OnPingDataReceive(int *pnBufSize, unsigned char **pbyDataReceive)
  226. {
  227.     return true;
  228. }
  229. int CPingSocket::OnPingStatus(int nOccurEvent)
  230. {
  231.     int nResult = false;
  232.     
  233.     switch (nOccurEvent)
  234.     {
  235.     case PINGEVENT_TESTBREAK:
  236.         nResult = false;
  237.         
  238.     case PINGEVENT_REPEAT:
  239.         nResult = true;
  240.         
  241.     default:
  242.         nResult = true;
  243.         break;
  244.     }
  245.     
  246.     return nResult;
  247. }
  248. void CPingSocket::OnErrorHandler()
  249. {
  250.     DoEventNotify(PINGEVENT_OCCURERROR);
  251. }
  252. int CPingSocket::DoEventNotify(int nOccurEvent)
  253. {
  254.     return OnPingStatus(nOccurEvent);
  255. }
  256.