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

📄 udpsocket.cpp

📁 电驴的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
				//
				// NOTE: To properly distinguish between the two packets which are both useing the same opcode...
				// the first two bytes of <challenge> (in network byte order) have to be an invalid <name_len> at least.

				CSafeMemFile srvinfo(packet, size);
				if (size >= 8 && PeekUInt16(packet) == INV_SERV_DESC_LEN)
				{
					if (update->GetDescReqChallenge() != 0 && PeekUInt32(packet) == update->GetDescReqChallenge())
					{
						update->SetDescReqChallenge(0);
						(void)srvinfo.ReadUInt32(); // skip challenge
						UINT uTags = srvinfo.ReadUInt32();
						for (UINT i = 0; i < uTags; i++)
						{
							CTag tag(&srvinfo, update->GetUnicodeSupport());
							if (tag.GetNameID() == ST_SERVERNAME && tag.IsStr())
								update->SetListName(tag.GetStr());
							else if (tag.GetNameID() == ST_DESCRIPTION && tag.IsStr())
								update->SetDescription(tag.GetStr());
							else if (tag.GetNameID() == ST_DYNIP && tag.IsStr())
								update->SetDynIP(tag.GetStr());
							else if (tag.GetNameID() == ST_VERSION && tag.IsStr())
								update->SetVersion(tag.GetStr());
							else if (tag.GetNameID() == ST_VERSION && tag.IsInt()){
								CString strVersion;
								strVersion.Format(_T("%u.%u"), tag.GetInt() >> 16, tag.GetInt() & 0xFFFF);
								update->SetVersion(strVersion);
							}
							else if (tag.GetNameID() == ST_AUXPORTSLIST && tag.IsStr())
								// currently not implemented.
								; // <string> = <port> [, <port>...]
							else{
								if (thePrefs.GetDebugServerUDPLevel() > 0)
									Debug(_T("***NOTE: Unknown tag in OP_ServerDescRes: %s\n"), tag.GetFullInfo());
							}
						}
					}
					else
					{
						// A server sent us a new server description packet (including a challenge) although we did not
						// ask for it. This may happen, if there are multiple servers running on the same machine with
						// multiple IPs. If such a server is asked for a description, the server will answer 2 times,
						// but with the same IP.

						if (thePrefs.GetDebugServerUDPLevel() > 0)
							Debug(_T("***NOTE: Received unexpected new format OP_ServerDescRes from %s:%u with challenge %08x (waiting on packet with challenge %08x)\n"), ipstr(nIP), nUDPPort-4, PeekUInt32(packet), update->GetDescReqChallenge());
						; // ignore this packet
					}
				}
				else
				{
					CString strName = srvinfo.ReadString(update->GetUnicodeSupport());
					CString strDesc = srvinfo.ReadString(update->GetUnicodeSupport());
					update->SetDescription(strDesc);
					update->SetListName(strName);
				}

				if (thePrefs.GetDebugServerUDPLevel() > 0){
					UINT uAddData = srvinfo.GetLength() - srvinfo.GetPosition();
					if (uAddData)
						Debug(_T("***NOTE: ServerUDPMessage from %s:%u - OP_ServerDescRes:  ***AddData: %s\n"), ipstr(nIP), nUDPPort-4, DbgGetHexDump(packet + srvinfo.GetPosition(), uAddData));
				}
				theApp.emuledlg->serverwnd->serverlistctrl.RefreshServer(update);
				break;
			}
			default:
				if (thePrefs.GetDebugServerUDPLevel() > 0)
					Debug(_T("***NOTE: ServerUDPMessage from %s:%u - Unknown packet: opcode=0x%02X  %s\n"), ipstr(nIP), nUDPPort-4, opcode, DbgGetHexDump(packet, size));
				return false;
		}

		return true;
	}
	catch(CFileException* error){
		TCHAR szError[MAX_CFEXP_ERRORMSG];
		error->m_strFileName = _T("server UDP packet");
		if (!error->GetErrorMessage(szError, ARRSIZE(szError)))
			szError[0] = _T('\0');
		ProcessPacketError(size, opcode, nIP, nUDPPort-4, szError);
		error->Delete();
		//ASSERT(0);
		if (opcode==OP_GLOBSEARCHRES || opcode==OP_GLOBFOUNDSOURCES)
			return true;
	}
	catch(CMemoryException* error){
		TCHAR szError[MAX_CFEXP_ERRORMSG];
		if (!error->GetErrorMessage(szError, ARRSIZE(szError)))
			szError[0] = _T('\0');
		ProcessPacketError(size, opcode, nIP, nUDPPort-4, szError);
		error->Delete();
		//ASSERT(0);
		if (opcode==OP_GLOBSEARCHRES || opcode==OP_GLOBFOUNDSOURCES)
			return true;
	}
	catch(CString error){
		ProcessPacketError(size, opcode, nIP, nUDPPort-4, error);
		//ASSERT(0);
	}
	catch(...){
		ProcessPacketError(size, opcode, nIP, nUDPPort-4, _T("Unknown exception"));
		ASSERT(0);
	}

	return false;
}

void CUDPSocket::ProcessPacketError(UINT size, UINT opcode, uint32 nIP, uint16 nTCPPort, LPCTSTR pszError)
{
	if (thePrefs.GetVerbose())
	{
		CString strName;
		CServer* pServer = theApp.serverlist->GetServerByAddress(ipstr(nIP), nTCPPort);
		if (pServer)
			strName = _T(" (") + pServer->GetListName() + _T(")");
		AddDebugLogLine(false, _T("Error: Failed to process server UDP packet from %s:%u%s opcode=0x%02x size=%u - %s"), ipstr(nIP), nTCPPort, strName, opcode, size, pszError);
	}
}

void CUDPSocket::AsyncResolveDNS(LPCSTR lpszHostAddressA, UINT nHostPort)
{
	if (m_DnsTaskHandle){
		WSACancelAsyncRequest(m_DnsTaskHandle);
		m_DnsTaskHandle = NULL;
	}

	// see if we have a ip already
	SOCKADDR_IN sockAddr = {0};
	sockAddr.sin_family = AF_INET;
	sockAddr.sin_addr.s_addr = inet_addr(lpszHostAddressA);
	sockAddr.sin_port = htons((u_short)nHostPort);

	// backup for send socket
	m_SaveAddr = sockAddr;

	if (sockAddr.sin_addr.s_addr == INADDR_NONE){
		/* Resolve hostname "hostname" asynchronously */ 
		memset(m_DnsHostBuffer, 0, sizeof(m_DnsHostBuffer));

		m_DnsTaskHandle = WSAAsyncGetHostByName(
			m_hWndResolveMessage,
			WM_DNSLOOKUPDONE,
			lpszHostAddressA,
			m_DnsHostBuffer,
			MAXGETHOSTSTRUCT);

		if (m_DnsTaskHandle == NULL){
			if (thePrefs.GetVerbose())
				AddDebugLogLine(false, _T("Error: Server UDP socket: Failed to resolve address for '%hs' - %s"), lpszHostAddressA, GetErrorMessage(GetLastError(), 1));
			delete[] m_sendbuffer;
			m_sendbuffer = NULL;
			delete m_cur_server;
			m_cur_server = NULL;
		}
	}
	else{
		SendBuffer();
	}
}

void CUDPSocket::DnsLookupDone(WPARAM wp, LPARAM lp){
	m_DnsTaskHandle = NULL;

	/* An asynchronous database routine completed. */
	if (WSAGETASYNCERROR(lp) != 0){
		if (thePrefs.GetVerbose())
			AddDebugLogLine(false, _T("Error: Server UDP socket: Failed to resolve address for server '%s' (%s) - %s"), m_cur_server ? m_cur_server->GetListName() : _T(""), m_cur_server ? m_cur_server->GetAddress() : _T(""), GetErrorMessage(WSAGETASYNCERROR(lp), 1));
		delete[] m_sendbuffer;
		m_sendbuffer = NULL;
		delete m_cur_server;
		m_cur_server = NULL;
		return;
	}
	if (m_SaveAddr.sin_addr.s_addr == INADDR_NONE){
		// get the structure length
		int iBufLen = WSAGETASYNCBUFLEN(lp);
		if (iBufLen >= sizeof(HOSTENT)){
			LPHOSTENT pHost = (LPHOSTENT)m_DnsHostBuffer;
			if (pHost->h_length == 4 && pHost->h_addr_list && pHost->h_addr_list[0])
				m_SaveAddr.sin_addr.s_addr = ((LPIN_ADDR)(pHost->h_addr_list[0]))->s_addr;
		}
		// also reset the receive buffer
		memset(m_DnsHostBuffer, 0, sizeof(m_DnsHostBuffer));
	}
	if (m_cur_server){
		if (m_SaveAddr.sin_addr.s_addr != INADDR_NONE){
			bool bRemoveServer = false;
			if (!IsGoodIP(m_SaveAddr.sin_addr.s_addr)){
				if (thePrefs.GetLogFilteredIPs())
					AddDebugLogLine(false, _T("Resolved IP for server '%s' is %s - Invalid IP or LAN address, server deleted."), m_cur_server->GetListName(), ipstr(m_SaveAddr.sin_addr.s_addr));
				bRemoveServer = true;
			}
			if (!bRemoveServer && theApp.ipfilter->IsFiltered(m_SaveAddr.sin_addr.s_addr)){
				if (thePrefs.GetLogFilteredIPs())
					AddDebugLogLine(false, _T("Resolved IP for server '%s' is %s - Found in IP filter, server deleted."), m_cur_server->GetListName(), ipstr(m_SaveAddr.sin_addr.s_addr));
				bRemoveServer = true;
			}

			if (!bRemoveServer){
				CServer* update = theApp.serverlist->GetServerByAddress(m_cur_server->GetAddress(),m_cur_server->GetPort());
			    if (update)
				    update->SetIP(m_SaveAddr.sin_addr.S_un.S_addr);
				SendBuffer();
			}
			else{
				CServer* todel = theApp.serverlist->GetServerByAddress(m_cur_server->GetAddress(), m_cur_server->GetPort());
				if (todel)
					theApp.emuledlg->serverwnd->serverlistctrl.RemoveServer(todel);
				delete m_cur_server;
				m_cur_server = NULL;
				delete[] m_sendbuffer;
				m_sendbuffer = NULL;
				m_sendblen = 0;
			}
		}
		else{
			// still no valid IP for this server - delete packet
			if (thePrefs.GetVerbose())
				AddDebugLogLine(false, _T("Error: Server UDP socket: Failed to resolve address for server '%s' (%s)"), m_cur_server->GetListName(), m_cur_server->GetAddress());
			delete m_cur_server;
			m_cur_server = NULL;
			delete[] m_sendbuffer;
			m_sendbuffer = NULL;
			m_sendblen = 0;
		}
	}
}

void CUDPSocket::OnSend(int nErrorCode){
	if (nErrorCode){
		if (thePrefs.GetVerbose())
			AddDebugLogLine(false, _T("Error: Server UDP socket: Failed to send packet - %s"), GetErrorMessage(nErrorCode, 1));
		return;
	}
	m_bWouldBlock = false;

// ZZ:UploadBandWithThrottler (UDP) -->
    sendLocker.Lock();
    if(!controlpacket_queue.IsEmpty()) {
        theApp.uploadBandwidthThrottler->QueueForSendingControlPacket(this);
    }
    sendLocker.Unlock();
// <-- ZZ:UploadBandWithThrottler (UDP)
}

SocketSentBytes CUDPSocket::SendControlData(uint32 maxNumberOfBytesToSend, uint32 minFragSize) { // ZZ:UploadBandWithThrottler (UDP)
// ZZ:UploadBandWithThrottler (UDP) -->
	// NOTE: *** This function is invoked from a *different* thread!
    sendLocker.Lock();

    uint32 sentBytes = 0;
// <-- ZZ:UploadBandWithThrottler (UDP)
    while (controlpacket_queue.GetHeadPosition() != 0 && !IsBusy() && sentBytes < maxNumberOfBytesToSend) // ZZ:UploadBandWithThrottler (UDP)
	{
		SServerUDPPacket* packet = controlpacket_queue.GetHead();
        int sendSuccess = SendTo(packet->packet, packet->size, packet->dwIP, packet->nPort);
		if (sendSuccess >= 0){
            if(sendSuccess > 0) {
                sentBytes += packet->size; // ZZ:UploadBandWithThrottler (UDP)
            }

			controlpacket_queue.RemoveHead();
			delete[] packet->packet;
			delete packet;
		}
	}

// ZZ:UploadBandWithThrottler (UDP) -->
    if(!IsBusy() && !controlpacket_queue.IsEmpty()) {
        theApp.uploadBandwidthThrottler->QueueForSendingControlPacket(this);
    }
    sendLocker.Unlock();

    SocketSentBytes returnVal = { true, 0, sentBytes };
    return returnVal;
// <-- ZZ:UploadBandWithThrottler (UDP)
}

int CUDPSocket::SendTo(uint8* lpBuf, int nBufLen, uint32 dwIP, uint16 nPort){
	// NOTE: *** This function is invoked from a *different* thread!
	int iResult = CAsyncSocket::SendTo(lpBuf, nBufLen, nPort, ipstr(dwIP));
	if (iResult == SOCKET_ERROR){
		DWORD dwError = GetLastError();
		if (dwError == WSAEWOULDBLOCK){
			m_bWouldBlock = true;
			return -1; // blocked
		}
		else{
			if (thePrefs.GetVerbose())
				theApp.QueueDebugLogLine(false, _T("Error: Server UDP socket: Failed to send packet to %s:%u - %s"), ipstr(dwIP), nPort, GetErrorMessage(dwError, 1));
			return 0; // error
		}
	}
	return 1; // success
}

void CUDPSocket::SendBuffer(){
	if(m_cur_server && m_sendbuffer){
		u_short nPort = ntohs(m_SaveAddr.sin_port);
// ZZ:UploadBandWithThrottler (UDP) -->
		SServerUDPPacket* newpending = new SServerUDPPacket;
		newpending->dwIP = m_SaveAddr.sin_addr.s_addr;
		newpending->nPort = nPort;
		newpending->packet = m_sendbuffer;
		newpending->size = m_sendblen;
        sendLocker.Lock();
		controlpacket_queue.AddTail(newpending);
        sendLocker.Unlock();
        theApp.uploadBandwidthThrottler->QueueForSendingControlPacket(this);
// <-- ZZ:UploadBandWithThrottler (UDP)

		m_sendbuffer = NULL;
		m_sendblen = 0;
		delete m_cur_server;
		m_cur_server = NULL;
	}
}

void CUDPSocket::SendPacket(Packet* packet,CServer* host){
	USES_CONVERSION;
	// if the last DNS query did not yet return, we may still have a packet queued - delete it
	if (thePrefs.GetVerbose() && m_cur_server)
		AddDebugLogLine(false, _T("Warning: Server UDP socket: Timeout occured when trying to resolve address for server '%s' (%s)"), m_cur_server->GetListName(), m_cur_server->GetAddress());
	delete m_cur_server;
	m_cur_server = NULL;
	delete[] m_sendbuffer;
	m_sendbuffer = NULL;
	m_sendblen = 0;

	m_cur_server = new CServer(host);
	m_sendbuffer = new uint8[packet->size+2];
	memcpy(m_sendbuffer,packet->GetUDPHeader(),2);
	memcpy(m_sendbuffer+2,packet->pBuffer,packet->size);
	m_sendblen = packet->size+2;
	AsyncResolveDNS(T2CA(m_cur_server->GetAddress()),m_cur_server->GetPort()+4);
}

⌨️ 快捷键说明

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