⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pinger.cpp

📁 电驴的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	int nAddrLen = sizeof(struct sockaddr_in); 
	char bufICMP[1500];             // allow full MTU

	// clear ICMP socket before sending UDP - not best solution, but may be needed to exclude late responses etc
	u_long bytes2read = 0;
	do {
		nRet = ioctlsocket(is, FIONREAD, &bytes2read);
		if (bytes2read > 0) {       // ignore errors here
			sa.sin_family = AF_INET;
			sa.sin_addr.s_addr = INADDR_ANY;	
			sa.sin_port = 0;

			nRet = recvfrom (is,    /* socket */ 
				(LPSTR)bufICMP,     /* buffer */ 
				1500,               /* length */ 
				0,                  /* flags  */ 
				(sockaddr*)&sa,     /* source */ 
				&nAddrLen);         /* addrlen*/

			//if (lastTimeOut) lastTimeOut--;
			//if (!lastTimeOut && toNowTimeOut) {
			//		toNowTimeOut--;
			//		if (toNowTimeOut) lastTimeOut = 3;
			//}
		}
	} while (bytes2read > 0);

	// set TTL value for UDP packet - should success with winsock 2
	// NB! take care about IP_TTL value - it's redefined in Ws2tcpip.h!
	// TODO: solve next problem correctly:
	// eMule is linking sockets functions using wsock32.lib (IP_TTL=7)
	// to use IP_TTL define, we must enforce linker to bind this function 
	// to ws2_32.lib (IP_TTL=4) (linker options: ignore wsock32.lib)
	nRet = setsockopt(us, IPPROTO_IP, IP_TTL, (char*)&nTTL, sizeof(int));
	if (nRet==SOCKET_ERROR) { 
		DWORD lastError = WSAGetLastError();
        PingStatus returnValue;
		returnValue.success = false;
		returnValue.delay = TIMEOUT;
		returnValue.error = lastError;
		//if (toNowTimeOut < 3) toNowTimeOut++;
		//	lastTimeOut = 3;
		return returnValue;
	} 

	sa.sin_family = AF_INET;
	sa.sin_addr.s_addr = lAddr;	
	sa.sin_port = htons(UDP_PORT);

	// send lonely UDP packet with almost minimal content (0 bytes is allowed too, but no data will be sent then)
	nRet = sendto(us, (LPSTR)&nTTL, 4, 0, (sockaddr*)&sa, sizeof(sa));  // send four bytes - TTL :)
    CTimeTick m_time;
    m_time.Tick();
	if (nRet==SOCKET_ERROR) { 
		DWORD lastError = WSAGetLastError();
        PingStatus returnValue;
		returnValue.success = false;
		returnValue.error = lastError;
		//if (toNowTimeOut < 3) toNowTimeOut++;
		//	lastTimeOut = 3;
		return returnValue;
	} 

	IPHeader* reply = (IPHeader*)bufICMP;

	bytes2read = 0;
	int timeoutOpt = TIMEOUT;
	bool noRcvTimeOut = false;
	nRet = setsockopt(is, SOL_SOCKET, SO_RCVTIMEO, (const char*) &timeoutOpt, sizeof(timeoutOpt));
	if (nRet==SOCKET_ERROR)
		noRcvTimeOut = true;

    float usResTime = 0.0f;
	while((usResTime += m_time.Tick()) < TIMEOUT){
		if (noRcvTimeOut){
			nRet = ioctlsocket(is, FIONREAD, &bytes2read);
			if (nRet != 0) {
				DWORD lastError = WSAGetLastError();
                PingStatus returnValue;
				returnValue.success = false;
				returnValue.delay = TIMEOUT;
				returnValue.error = lastError;
				//if (toNowTimeOut < 3) toNowTimeOut++;
				//	lastTimeOut = 3;
				return returnValue;
			}
			if (bytes2read > 0) {       // read and filter incoming ICMP

			} else {
				Sleep(1);         // share time with other threads
				continue;
			}
		}
		sa.sin_family = AF_INET;
		sa.sin_addr.s_addr = INADDR_ANY;	
		sa.sin_port = 0;
		nRet = recvfrom (is,    /* socket */ 
			(LPSTR)bufICMP,     /* buffer */ 
			1500,               /* length */ 
			0,                  /* flags  */ 
			(sockaddr*)&sa,     /* source */ 
			&nAddrLen);         /* addrlen*/ 

		usResTime += m_time.Tick();
		if (nRet==SOCKET_ERROR) { 
			DWORD lastError = WSAGetLastError();
            PingStatus returnValue;
			returnValue.success = false;
			returnValue.delay = TIMEOUT;
			returnValue.error = lastError;
			//if (toNowTimeOut < 3) toNowTimeOut++;
			//	lastTimeOut = 3;
			return returnValue;
		} 

		unsigned short header_len = reply->h_len * 4;
		ICMPHeader* icmphdr = (ICMPHeader*)(bufICMP + header_len);
		IN_ADDR stDestAddr;

		stDestAddr.s_addr = reply->source_ip;

		if (((icmphdr->type == ICMP_TTL_EXPIRE) || (icmphdr->type == ICMP_DEST_UNREACH)) &&
			(icmphdr->UDP.dest_port == htons(UDP_PORT)) && (icmphdr->hdrsent.dest_ip == lAddr)) {

            PingStatus returnValue;

            if(icmphdr->type == ICMP_TTL_EXPIRE) {
                returnValue.success = true;
			    returnValue.status = IP_TTL_EXPIRED_TRANSIT;
			    returnValue.delay = usResTime;
			    returnValue.destinationAddress = stDestAddr.s_addr;
			    returnValue.ttl = ttl;
            } else {
                returnValue.success = true;
                returnValue.status = IP_DEST_HOST_UNREACHABLE;
			    returnValue.delay = usResTime;
			    returnValue.destinationAddress = stDestAddr.s_addr;
			    returnValue.ttl = 64 - (reply->ttl & 63);
            }

			if(doLog) {
				theApp.QueueDebugLogLine(false,_T("Reply (UDP-pinger) from %s: bytes=%d time=%3.2fms TTL=%i"),
					ipstr(stDestAddr),
					nRet,
					usResTime,
					returnValue.ttl);
			}
			return returnValue;
		} else {              // verbose log filtered packets info (not seen yet...)
			//if (lastTimeOut) lastTimeOut--;
			//if (!lastTimeOut && toNowTimeOut) {
			//		toNowTimeOut--;
			//		if (toNowTimeOut) lastTimeOut = 3;
			//}
			if(doLog) {
				theApp.QueueDebugLogLine(false,_T("Filtered reply (UDP-pinger) from %s: bytes=%d time=%3.2fms TTL=%i type=%i"),
					ipstr(stDestAddr),
					nRet,
					usResTime,
					64 - (reply->ttl & 63),
					icmphdr->type);
			}
		}
	}
	//if (usResTime >= TIMEOUT) {
	//	if (toNowTimeOut < 3) toNowTimeOut++;
	//	lastTimeOut = 3;
	//}
	// UDPing reworked ping sequence end <--

    PingStatus returnValue;
	returnValue.success = false;
	returnValue.delay = TIMEOUT;
	returnValue.error = IP_REQ_TIMED_OUT;

    return returnValue;
}

PingStatus Pinger::PingICMP(uint32 lAddr, uint32 ttl, bool doLog) {
    PingStatus returnValue;

    IN_ADDR stDestAddr;
    char achRepData[sizeof(ICMPECHO) + BUFSIZE];

    // Address is assumed to be ok
    stDestAddr.s_addr = lAddr;
    stIPInfo.Ttl = ttl;

    CTimeTick m_time;
	m_time.Tick();
    // Send the ICMP Echo Request and read the Reply
    DWORD dwReplyCount = lpfnIcmpSendEcho(hICMP, 
                                    stDestAddr.s_addr,
                                    0, // databuffer
                                    0, // DataLen, length of databuffer
                                    &stIPInfo, 
                                    achRepData, 
                                    sizeof(achRepData), 
                                    TIMEOUT
                            );
	float usResTime=m_time.Tick();
    if (dwReplyCount != 0) {
        long pingTime = *(u_long *) &(achRepData[8]);

        IN_ADDR stDestAddr;

        stDestAddr.s_addr = *(u_long *)achRepData;

        returnValue.success = true;
        returnValue.status = *(DWORD *) &(achRepData[4]);
		returnValue.delay = (m_time.isPerformanceCounter() && (pingTime <= 20 || pingTime%10 == 0) && (pingTime+10 > usResTime && usResTime+10 > pingTime )? usResTime : pingTime);
        returnValue.destinationAddress = stDestAddr.s_addr;
        returnValue.ttl = (returnValue.status != IP_SUCCESS)?ttl:(*(char *)&(achRepData[20]))&0x00FF;

        if(doLog) {
            theApp.QueueDebugLogLine(false,_T("Reply (ICMP-pinger) from %s: bytes=%d time=%3.2fms (%3.2fms %ldms) TTL=%i"),
                                                        ipstr(stDestAddr),
                                                        *(u_long *) &(achRepData[12]),
                                                        returnValue.delay,
                                                        m_time.isPerformanceCounter() ? usResTime : -1.0f, 
                                                        (u_long)(achRepData[8]),
                                                        returnValue.ttl);
        }
    } else {
        DWORD lastError = GetLastError();
        returnValue.success = false;
        returnValue.error = lastError;
        if(doLog) {
			theApp.QueueDebugLogLine(false,_T("Error from %s: Error=%i"),
				ipstr(stDestAddr),
				returnValue.error);
        }
    }

    return returnValue;
}


void Pinger::PIcmpErr(int nICMPErr) {
    int  nErrIndex = nICMPErr - IP_STATUS_BASE;

    if ((nICMPErr > MAX_ICMP_ERR_STRING) || 
        (nICMPErr < IP_STATUS_BASE+1)) {

        // Error value is out of range, display normally
		theApp.QueueDebugLogLine(false,_T("Pinger: %s"),GetErrorMessage(nICMPErr,1));
    } else {

        // Display ICMP Error String
        theApp.QueueDebugLogLine(false,_T("%s"), aszSendEchoErr[nErrIndex]);
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -