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

📄 udpsocket.cpp

📁 电驴的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//this file is part of eMule
//Copyright (C)2002 Merkur ( devs@emule-project.net / http://www.emule-project.net )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "stdafx.h"
#include "emule.h"
#include "UDPSocket.h"
#include "SearchList.h"
#include "DownloadQueue.h"
#include "Statistics.h"
#include "Server.h"
#include "Preferences.h"
#include "OtherFunctions.h"
#include "ServerList.h"
#include "Opcodes.h"
#include "SafeFile.h"
#include "PartFile.h"
#include "Packets.h"
#include "IPFilter.h"
#include "emuledlg.h"
#include "ServerWnd.h"
#include "SearchDlg.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


#pragma pack(1)
struct SServerUDPPacket
{
	uint8* packet;
	int size;
	uint32 dwIP;
	uint16 nPort;
};
#pragma pack()


CUDPSocketWnd::CUDPSocketWnd(){
}

BEGIN_MESSAGE_MAP(CUDPSocketWnd, CWnd)
	ON_MESSAGE(WM_DNSLOOKUPDONE, OnDNSLookupDone)
END_MESSAGE_MAP()

LRESULT CUDPSocketWnd::OnDNSLookupDone(WPARAM wParam,LPARAM lParam){
	m_pOwner->DnsLookupDone(wParam,lParam);
	return true;
};

CUDPSocket::CUDPSocket(){
	m_hWndResolveMessage = NULL;
	m_sendbuffer = NULL;
	m_cur_server = NULL;
	m_DnsTaskHandle = NULL;
	m_bWouldBlock = false;
}

CUDPSocket::~CUDPSocket(){
    theApp.uploadBandwidthThrottler->RemoveFromAllQueues(this); // ZZ:UploadBandWithThrottler (UDP)

    delete m_cur_server;
	delete[] m_sendbuffer;
	POSITION pos = controlpacket_queue.GetHeadPosition();
	while (pos){
		SServerUDPPacket* p = controlpacket_queue.GetNext(pos);
		delete[] p->packet;
		delete p;
	}
	m_udpwnd.DestroyWindow();
}

bool CUDPSocket::Create(){
	if (thePrefs.GetServerUDPPort()){
	    VERIFY( m_udpwnd.CreateEx(0, AfxRegisterWndClass(0),_T("Emule Socket Wnd"),WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL));
	    m_hWndResolveMessage = m_udpwnd.m_hWnd;
	    m_udpwnd.m_pOwner = this;
		if (!CAsyncSocket::Create(thePrefs.GetServerUDPPort()==0xFFFF ? 0 : thePrefs.GetServerUDPPort(), SOCK_DGRAM, FD_READ | FD_WRITE)){
			AddLogLine(true, _T("Error: Server UDP socket: Failed to create server UDP socket on port - %s"), GetErrorMessage(GetLastError()));
			return false;
		}
		//return true;
		// VeryCD版
		if(thePrefs.GetUPnPNat()){
			CString client;
			UINT port;
			CUPnPNat::UPNPNAT_MAPPING mapping;

			GetSockName(client, port);
			mapping.internalPort = mapping.externalPort = port;
			mapping.protocol = CUPnPNat::UNAT_UDP;
			mapping.description = "Server UDP Port";
			theApp.AddUPnPNatPort(&mapping, thePrefs.GetUPnPNatTryRandom());
		}
		return true;
		// VeryCD版
	}
	return false;
}

void CUDPSocket::OnReceive(int nErrorCode){
	if (nErrorCode){
		if (thePrefs.GetVerbose())
			AddDebugLogLine(false, _T("Error: Server UDP socket: Receive failed - %s"), GetErrorMessage(nErrorCode, 1));
	}

	uint8 buffer[5000];
	SOCKADDR_IN sockAddr = {0};
	int iSockAddrLen = sizeof sockAddr;
	int length = ReceiveFrom(buffer, sizeof buffer, (SOCKADDR*)&sockAddr, &iSockAddrLen);
	if (length != SOCKET_ERROR)
	{
		if (buffer[0] == OP_EDONKEYPROT)
			ProcessPacket(buffer+2, length-2, buffer[1], sockAddr.sin_addr.S_un.S_addr, ntohs(sockAddr.sin_port));
		else if (thePrefs.GetDebugServerUDPLevel() > 0)
			Debug(_T("***NOTE: ServerUDPMessage from %s:%u - Unknown protocol 0x%02x\n"), ipstr(sockAddr.sin_addr), ntohs(sockAddr.sin_port)-4, buffer[0]);
	}
	else
	{
		DWORD dwError = WSAGetLastError();
		if (thePrefs.GetVerbose())
		{
			// Depending on local and remote OS and depending on used local (remote?) router we may receive
			// WSAECONNRESET errors. According some KB articels, this is a special way of winsock to report 
			// that a sent UDP packet was not received by the remote host because it was not listening on 
			// the specified port -> no server running there.
			//
			CString strServerInfo;
			if (iSockAddrLen > 0 && sockAddr.sin_addr.S_un.S_addr != 0 && sockAddr.sin_addr.S_un.S_addr != INADDR_NONE)
				strServerInfo.Format(_T(" from %s:%u"), ipstr(sockAddr.sin_addr), ntohs(sockAddr.sin_port));
			AddDebugLogLine(false, _T("Error: Server UDP socket, failed to receive data%s: %s"), strServerInfo, GetErrorMessage(dwError, 1));
		}
		if (dwError == WSAECONNRESET)
		{
			CServer* pServer = theApp.serverlist->GetServerByAddress(ipstr(sockAddr.sin_addr), ntohs(sockAddr.sin_port)-4);
			if (pServer && pServer->GetChallenge()==0)
				pServer->AddFailedCount();
		}
	}
}

bool CUDPSocket::ProcessPacket(uint8* packet, UINT size, UINT opcode, uint32 nIP, uint16 nUDPPort){
	try{
		theStats.AddDownDataOverheadServer(size);
		CServer* update = theApp.serverlist->GetServerByAddress(ipstr(nIP), nUDPPort-4);
		if( update ){
			update->ResetFailedCount();
			theApp.emuledlg->serverwnd->serverlistctrl.RefreshServer( update );
		}
		switch(opcode){
			case OP_GLOBSEARCHRES:{
				CSafeMemFile data(packet, size);
				// process all search result packets
				int iLeft;
				int iPacket = 1;
				do{
					if (thePrefs.GetDebugServerUDPLevel() > 0){
						uint32 nClientID = *((uint32*)(packet+16));
						uint16 nClientPort = *((uint16*)(packet+20));
						Debug(_T("ServerUDPMessage from %s:%u - OP_GlobSearchResult(%u); %s\n"), ipstr(nIP), nUDPPort-4, iPacket++, DbgGetFileInfo((uchar*)packet), DbgGetClientID(nClientID), nClientPort);
					}
					uint16 uResultCount = theApp.searchlist->ProcessUDPSearchanswer(data, true/*update->GetUnicodeSupport()*/, nIP, nUDPPort-4);
					theApp.emuledlg->searchwnd->AddUDPResult(uResultCount);

					// check if there is another source packet
					iLeft = (int)(data.GetLength() - data.GetPosition());
					if (iLeft >= 2){
						uint8 protocol = data.ReadUInt8();
						iLeft--;
						if (protocol != OP_EDONKEYPROT){
							data.Seek(-1, SEEK_CUR);
							iLeft += 1;
							break;
						}

						uint8 opcode = data.ReadUInt8();
						iLeft--;
						if (opcode != OP_GLOBSEARCHRES){
							data.Seek(-2, SEEK_CUR);
							iLeft += 2;
							break;
						}
					}
				}
				while (iLeft > 0);

				if (iLeft > 0 && thePrefs.GetDebugServerUDPLevel() > 0){
					Debug(_T("OP_GlobSearchResult contains %d additionl bytes\n"), iLeft);
					if (thePrefs.GetDebugServerUDPLevel() > 1)
						DebugHexDump(data);
				}
				break;
			}
			case OP_GLOBFOUNDSOURCES:{
				CSafeMemFile data(packet, size);
				// process all source packets
				int iLeft;
				int iPacket = 1;
				do{
					uchar fileid[16];
					data.ReadHash16(fileid);
					if (thePrefs.GetDebugServerUDPLevel() > 0)
						Debug(_T("ServerUDPMessage from %s:%u - OP_GlobFoundSources(%u); %s\n"), ipstr(nIP), nUDPPort-4, iPacket++, DbgGetFileInfo(fileid));
					if (CPartFile* file = theApp.downloadqueue->GetFileByID(fileid))
						file->AddSources(&data, nIP, nUDPPort-4);
					else{
						// skip sources for that file
						UINT count = data.ReadUInt8();
						data.Seek(count*(4+2), SEEK_SET);
					}

					// check if there is another source packet
					iLeft = (int)(data.GetLength() - data.GetPosition());
					if (iLeft >= 2){
						uint8 protocol = data.ReadUInt8();
						iLeft--;
						if (protocol != OP_EDONKEYPROT){
							data.Seek(-1, SEEK_CUR);
							iLeft += 1;
							break;
						}

						uint8 opcode = data.ReadUInt8();
						iLeft--;
						if (opcode != OP_GLOBFOUNDSOURCES){
							data.Seek(-2, SEEK_CUR);
							iLeft += 2;
							break;
						}
					}
				}
				while (iLeft > 0);

				if (iLeft > 0 && thePrefs.GetDebugServerUDPLevel() > 0){
					Debug(_T("OP_GlobFoundSources contains %d additional bytes\n"), iLeft);
					if (thePrefs.GetDebugServerUDPLevel() > 1)
						DebugHexDump(data);
				}
				break;
			}
 			case OP_GLOBSERVSTATRES:{
				if (thePrefs.GetDebugServerUDPLevel() > 0)
					Debug(_T("ServerUDPMessage from %s:%u - OP_GlobServStatRes\n"), ipstr(nIP), nUDPPort-4);
				if( size < 12 || update == NULL )
					return true;
#define get_uint32(p)	*((uint32*)(p))
				uint32 challenge = get_uint32(packet);
				if (challenge != update->GetChallenge()){
					if (thePrefs.GetDebugServerUDPLevel() > 0)
						Debug(_T("***NOTE: Received unexpected challenge %08x (waiting on packet with challenge %08x)\n"), challenge, update->GetChallenge());
					return true;
				}
				update->SetChallenge(0);
				uint32 cur_user = get_uint32(packet+4);
				uint32 cur_files = get_uint32(packet+8);
				uint32 cur_maxusers = 0;
				uint32 cur_softfiles = 0;
				uint32 cur_hardfiles = 0;
				uint32 uUDPFlags = 0;
				uint32 uLowIDUsers = 0;
				if( size >= 16 ){
					cur_maxusers = get_uint32(packet+12);
				}
				if( size >= 24 ){
					cur_softfiles = get_uint32(packet+16);
					cur_hardfiles = get_uint32(packet+20);
				}
				if( size >= 28 ){
					uUDPFlags = get_uint32(packet+24);
					if (thePrefs.GetDebugServerUDPLevel() > 0){
						CString strInfo;
						strInfo.AppendFormat(_T(" UDP Flags=0x%08x"), uUDPFlags);
						const DWORD dwKnownBits = SRV_UDPFLG_EXT_GETSOURCES | SRV_UDPFLG_EXT_GETFILES;
						if (uUDPFlags & ~dwKnownBits)
							strInfo.AppendFormat(_T("  ***UnkBits=0x%08x"), uUDPFlags & ~dwKnownBits);
						if (uUDPFlags & SRV_UDPFLG_EXT_GETSOURCES)
							strInfo.AppendFormat(_T("  ExtGetSources=1"));
						if (uUDPFlags & SRV_UDPFLG_EXT_GETFILES)
							strInfo.AppendFormat(_T("  ExtGetFiles=1"));
						Debug(_T("%s\n"), strInfo);
					}
				}
				if( size >= 32 ){
					uLowIDUsers = get_uint32(packet+28);
					if (thePrefs.GetDebugServerUDPLevel() > 0)
						Debug(_T(" LowID users=%u\n"), uLowIDUsers);
				}
				if (thePrefs.GetDebugServerUDPLevel() > 0){
					if( size > 32 ){
					    Debug(_T("***NOTE: ServerUDPMessage from %s:%u - OP_GlobServStatRes:  ***AddData: %s\n"), ipstr(nIP), nUDPPort-4, DbgGetHexDump(packet+24, size-24));
					}
				}
				if( update ){
					update->SetPing( ::GetTickCount() - update->GetLastPinged() );
					update->SetUserCount( cur_user );
					update->SetFileCount( cur_files );
					update->SetMaxUsers( cur_maxusers );
					update->SetSoftFiles( cur_softfiles );
					update->SetHardFiles( cur_hardfiles );
					// if the received UDP flags do not match any already stored UDP flags, 
					// reset the server version string because the version (which was determined by last connecting to
					// that server) is most likely not accurat any longer.
					// this may also give 'false' results because we don't know the UDP flags when connecting to a server
					// with TCP.
					//if (update->GetUDPFlags() != uUDPFlags)
					//	update->SetVersion(_T(""));
					update->SetUDPFlags( uUDPFlags );
					update->SetLowIDUsers( uLowIDUsers );
					theApp.emuledlg->serverwnd->serverlistctrl.RefreshServer( update );
				}
#undef get_uint32
				break;
			}

 			case OP_SERVER_DESC_RES:{
				if (thePrefs.GetDebugServerUDPLevel() > 0)
					Debug(_T("ServerUDPMessage from %s:%u - OP_ServerDescRes\n"), ipstr(nIP), nUDPPort-4);
				if (!update)
					return true;

				// old packet: <name_len 2><name name_len><desc_len 2 desc_en>
				// new packet: <challenge 4><taglist>

⌨️ 快捷键说明

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