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

📄 kademliaudplistener.cpp

📁 电驴下载工具eMule0.47aVeryCD的源代码,可作分析测试也可用于P2P软件的开发研究.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	}

	ContactList *pResults = new ContactList;
	CUInt128 uIDResult;
	try
	{
		for (uint8 iIndex=0; iIndex<uNumContacts; iIndex++)
		{
			fileIO.ReadUInt128(&uIDResult);
			uint32 uIPResult = fileIO.ReadUInt32();
			uint16 uUDPPortResult = fileIO.ReadUInt16();
			uint16 uTCPPortResult = fileIO.ReadUInt16();
			uint8 uVersion = fileIO.ReadUInt8();
			if(::IsGoodIPPort(ntohl(uIPResult),uUDPPortResult))
			{
				pRoutingZone->Add(uIDResult, uIPResult, uUDPPortResult, uTCPPortResult, uVersion);
				pResults->push_back(new CContact(uIDResult, uIPResult, uUDPPortResult, uTCPPortResult, uTarget, uVersion));
			}
		}
	}
	catch(...)
	{
		delete pResults;
		throw;
	}
	CSearchManager::ProcessResponse(uTarget, uIP, uUDPPort, pResults);
}

void CKademliaUDPListener::Free(SSearchTerm* pSearchTerms)
{
	if(pSearchTerms)
	{
		if (pSearchTerms->m_pLeft)
			Free(pSearchTerms->m_pLeft);
		if (pSearchTerms->m_pRight)
			Free(pSearchTerms->m_pRight);
		delete pSearchTerms;
	}
}

static void TokenizeOptQuotedSearchTerm(LPCTSTR pszString, CStringWArray* lst)
{
	LPCTSTR pch = pszString;
	while (*pch != _T('\0'))
	{
		if (*pch == _T('\"'))
		{
			// Start of quoted string found. If there is no terminating quote character found,
			// the start quote character is just skipped. If the quoted string is empty, no
			// new entry is added to 'list'.
			//
			pch++;
			LPCTSTR pchNextQuote = _tcschr(pch, _T('\"'));
			if (pchNextQuote)
			{
				size_t nLenQuoted = pchNextQuote - pch;
				if (nLenQuoted)
					lst->Add(CString(pch, nLenQuoted));
				pch = pchNextQuote + 1;
			}
		}
		else
		{
			// Search for next delimiter or quote character
			//
			size_t nNextDelimiter = _tcscspn(pch, _T(INV_KAD_KEYWORD_CHARS) _T("\""));
			if (nNextDelimiter)
			{
				lst->Add(CString(pch, nNextDelimiter));
				pch += nNextDelimiter;
				if (*pch == _T('\0'))
					break;
				if (*pch == _T('\"'))
					continue;
			}
			pch++;
		}
	}
}

static CString* _pstrDbgSearchExpr;

SSearchTerm* CKademliaUDPListener::CreateSearchExpressionTree(CSafeMemFile& fileIO, int iLevel)
{
	// the max. depth has to match our own limit for creating the search expression
	// (see also 'ParsedSearchExpression' and 'GetSearchPacket')
	if (iLevel >= 24)
	{
		AddDebugLogLine(false, _T("***NOTE: Search expression tree exceeds depth limit!"));
		return NULL;
	}
	iLevel++;

	uint8 uOp = fileIO.ReadUInt8();
	if (uOp == 0x00)
	{
		uint8 uBoolOp = fileIO.ReadUInt8();
		if (uBoolOp == 0x00) // AND
		{
			SSearchTerm* pSearchTerm = new SSearchTerm;
			pSearchTerm->m_type = SSearchTerm::AND;
			if (_pstrDbgSearchExpr)
				_pstrDbgSearchExpr->Append(_T(" AND"));
			if ((pSearchTerm->m_pLeft = CreateSearchExpressionTree(fileIO, iLevel)) == NULL)
			{
				ASSERT(0);
				delete pSearchTerm;
				return NULL;
			}
			if ((pSearchTerm->m_pRight = CreateSearchExpressionTree(fileIO, iLevel)) == NULL)
			{
				ASSERT(0);
				Free(pSearchTerm->m_pLeft);
				delete pSearchTerm;
				return NULL;
			}
			return pSearchTerm;
		}
		else if (uBoolOp == 0x01) // OR
		{
			SSearchTerm* pSearchTerm = new SSearchTerm;
			pSearchTerm->m_type = SSearchTerm::OR;
			if (_pstrDbgSearchExpr)
				_pstrDbgSearchExpr->Append(_T(" OR"));
			if ((pSearchTerm->m_pLeft = CreateSearchExpressionTree(fileIO, iLevel)) == NULL)
			{
				ASSERT(0);
				delete pSearchTerm;
				return NULL;
			}
			if ((pSearchTerm->m_pRight = CreateSearchExpressionTree(fileIO, iLevel)) == NULL)
			{
				ASSERT(0);
				Free(pSearchTerm->m_pLeft);
				delete pSearchTerm;
				return NULL;
			}
			return pSearchTerm;
		}
		else if (uBoolOp == 0x02) // NOT
		{
			SSearchTerm* pSearchTerm = new SSearchTerm;
			pSearchTerm->m_type = SSearchTerm::NOT;
			if (_pstrDbgSearchExpr)
				_pstrDbgSearchExpr->Append(_T(" NOT"));
			if ((pSearchTerm->m_pLeft = CreateSearchExpressionTree(fileIO, iLevel)) == NULL)
			{
				ASSERT(0);
				delete pSearchTerm;
				return NULL;
			}
			if ((pSearchTerm->m_pRight = CreateSearchExpressionTree(fileIO, iLevel)) == NULL)
			{
				ASSERT(0);
				Free(pSearchTerm->m_pLeft);
				delete pSearchTerm;
				return NULL;
			}
			return pSearchTerm;
		}
		else
		{
			AddDebugLogLine(false, _T("*** Unknown boolean search operator 0x%02x (CreateSearchExpressionTree)"), uBoolOp);
			return NULL;
		}
	}
	else if (uOp == 0x01) // String
	{
		CKadTagValueString str(fileIO.ReadStringUTF8());

		KadTagStrMakeLower(str); // make lowercase, the search code expects lower case strings!
		if (_pstrDbgSearchExpr)
			_pstrDbgSearchExpr->AppendFormat(_T(" \"%ls\""), str);

		SSearchTerm* pSearchTerm = new SSearchTerm;
		pSearchTerm->m_type = SSearchTerm::String;
		pSearchTerm->m_pastr = new CStringWArray;

		// pre-tokenize the string term (care about quoted parts)
		TokenizeOptQuotedSearchTerm(str, pSearchTerm->m_pastr);

		return pSearchTerm;
	}
	else if (uOp == 0x02) // Meta tag
	{
		// read tag value
		CKadTagValueString strValue(fileIO.ReadStringUTF8());

		KadTagStrMakeLower(strValue); // make lowercase, the search code expects lower case strings!

		// read tag name
		CStringA strTagName;
		uint16 lenTagName = fileIO.ReadUInt16();
		fileIO.Read(strTagName.GetBuffer(lenTagName), lenTagName);
		strTagName.ReleaseBuffer(lenTagName);

		SSearchTerm* pSearchTerm = new SSearchTerm;
		pSearchTerm->m_type = SSearchTerm::MetaTag;
		pSearchTerm->m_pTag = new Kademlia::CKadTagStr(strTagName, strValue);
		if (_pstrDbgSearchExpr)
		{
			if (lenTagName == 1)
				_pstrDbgSearchExpr->AppendFormat(_T(" Tag%02X=\"%ls\""), (BYTE)strTagName[0], strValue);
			else
				_pstrDbgSearchExpr->AppendFormat(_T(" \"%s\"=\"%ls\""), strTagName, strValue);
		}
		return pSearchTerm;
	}
	else if (uOp == 0x03 || uOp == 0x08) // Numeric Relation (0x03=32-bit or 0x08=64-bit)
	{
		static const struct
		{
			SSearchTerm::ESearchTermType eSearchTermOp;
			LPCTSTR pszOp;
		}
		_aOps[] =
		    {
		        { SSearchTerm::OpEqual,			_T("=")		}, // mmop=0x00
		        { SSearchTerm::OpGreater,		_T(">")		}, // mmop=0x01
		        { SSearchTerm::OpLess,			_T("<")		}, // mmop=0x02
		        { SSearchTerm::OpGreaterEqual,	_T(">=")	}, // mmop=0x03
		        { SSearchTerm::OpLessEqual,		_T("<=")	}, // mmop=0x04
		        { SSearchTerm::OpNotEqual,		_T("<>")	}  // mmop=0x05
		    };

		// read tag value
		uint64 ullValue = (uOp == 0x03) ? fileIO.ReadUInt32() : fileIO.ReadUInt64();

		// read integer operator
		uint8 mmop = fileIO.ReadUInt8();
		if (mmop >= ARRSIZE(_aOps))
		{
			AddDebugLogLine(false, _T("*** Unknown integer search op=0x%02x (CreateSearchExpressionTree)"), mmop);
			return NULL;
		}

		// read tag name
		CStringA strTagName;
		uint16 uLenTagName = fileIO.ReadUInt16();
		fileIO.Read(strTagName.GetBuffer(uLenTagName), uLenTagName);
		strTagName.ReleaseBuffer(uLenTagName);

		SSearchTerm* pSearchTerm = new SSearchTerm;
		pSearchTerm->m_type = _aOps[mmop].eSearchTermOp;
		pSearchTerm->m_pTag = new Kademlia::CKadTagUInt64(strTagName, ullValue);

		if (_pstrDbgSearchExpr)
		{
			if (uLenTagName == 1)
				_pstrDbgSearchExpr->AppendFormat(_T(" Tag%02X%s%I64u"), (BYTE)strTagName[0], _aOps[mmop].pszOp, ullValue);
			else
				_pstrDbgSearchExpr->AppendFormat(_T(" \"%s\"%s%I64u"), strTagName, _aOps[mmop].pszOp, ullValue);
		}

		return pSearchTerm;
	}
	else
	{
		AddDebugLogLine(false, _T("*** Unknown search op=0x%02x (CreateSearchExpressionTree)"), uOp);
		return NULL;
	}
}

// Used in Kad1.0 only
void CKademliaUDPListener::Process_KADEMLIA_SEARCH_REQ (const byte *pbyPacketData, uint32 uLenPacket, uint32 uIP, uint16 uUDPPort)
{
	// Verify packet is expected size
	if (uLenPacket < 17)
	{
		CString strError;
		strError.Format(_T("***NOTE: Received wrong size (%u) packet in %hs"), uLenPacket, __FUNCTION__);
		throw strError;
	}

	CSafeMemFile fileIO( pbyPacketData, uLenPacket);
	CUInt128 uTarget;
	fileIO.ReadUInt128(&uTarget);
	uint8 uRestrictive = fileIO.ReadUInt8();

	if(uLenPacket == 17 )
	{
		if(uRestrictive)
			CKademlia::GetIndexed()->SendValidSourceResult(uTarget, uIP, uUDPPort, false, 0, 0);
		else
			CKademlia::GetIndexed()->SendValidKeywordResult(uTarget, NULL, uIP, uUDPPort, true, false, 0);
	}
	else if(uLenPacket > 17)
	{
		SSearchTerm* pSearchTerms = NULL;
		bool bOldClient = true;
		if (uRestrictive)
		{
			try
			{
#if defined(_DEBUG) || defined(USE_DEBUG_DEVICE)
				_pstrDbgSearchExpr = (thePrefs.GetDebugServerSearchesLevel() > 0) ? new CString : NULL;
#endif

				pSearchTerms = CreateSearchExpressionTree(fileIO, 0);
				if (_pstrDbgSearchExpr)
				{
					Debug(_T("KadSearchTerm=%s\n"), *_pstrDbgSearchExpr);
					delete _pstrDbgSearchExpr;
					_pstrDbgSearchExpr = NULL;
				}
			}
			catch(...)
			{
				Free(pSearchTerms);
				throw;
			}
			if (pSearchTerms == NULL)
				throw CString(_T("Invalid search expression"));
			if(uRestrictive>1)
				bOldClient = false;
		}
		else
			bOldClient = false;

		//Keyword request with added options.
		CKademlia::GetIndexed()->SendValidKeywordResult(uTarget, pSearchTerms, uIP, uUDPPort, bOldClient, false, 0x0000);
		Free(pSearchTerms);
	}
}

// Used in Kad2.0 only
void CKademliaUDPListener::Process_KADEMLIA2_SEARCH_KEY_REQ (const byte *pbyPacketData, uint32 uLenPacket, uint32 uIP, uint16 uUDPPort)
{
	CSafeMemFile fileIO( pbyPacketData, uLenPacket);
	CUInt128 uTarget;
	fileIO.ReadUInt128(&uTarget);
	uint16 uStartPosition = fileIO.ReadUInt16();
	bool uRestrictive = ((uStartPosition & 0x8000) == 0x8000);
	uStartPosition = uStartPosition & 0x7FFF;
	SSearchTerm* pSearchTerms = NULL;
	if (uRestrictive)
	{
		try
		{
#if defined(_DEBUG) || defined(USE_DEBUG_DEVICE)
			_pstrDbgSearchExpr = (thePrefs.GetDebugServerSearchesLevel() > 0) ? new CString : NULL;
#endif
			pSearchTerms = CreateSearchExpressionTree(fileIO, 0);
			if (_pstrDbgSearchExpr)
			{
				Debug(_T("KadSearchTerm=%s\n"), *_pstrDbgSearchExpr);
				delete _pstrDbgSearchExpr;
				_pstrDbgSearchExpr = NULL;
			}
		}
		catch(...)
		{
			Free(pSearchTerms);
			throw;
		}
		if (pSearchTerms == NULL)
			throw CString(_T("Invalid search expression"));
	}
	CKademlia::GetIndexed()->SendValidKeywordResult(uTarget, pSearchTerms, uIP, uUDPPort, false, true, uStartPosition);
	if(pSearchTerms)
		Free(pSearchTerms);
}

// Used in Kad2.0 only
void CKademliaUDPListener::Process_KADEMLIA2_SEARCH_SOURCE_REQ (const byte *pbyPacketData, uint32 uLenPacket, uint32 uIP, uint16 uUDPPort)
{
	CSafeMemFile fileIO( pbyPacketData, uLenPacket);
	CUInt128 uTarget;
	fileIO.ReadUInt128(&uTarget);
	uint16 uStartPosition = (fileIO.ReadUInt16() & 0x7FFF);
	uint64 uFileSize = fileIO.ReadUInt64();
	CKademlia::GetIndexed()->SendValidSourceResult(uTarget, uIP, uUDPPort, true, uStartPosition, uFileSize);
}

// Used in Kad1.0 only
void CKademliaUDPListener::Process_KADEMLIA_SEARCH_RES (const byte *pbyPacketData, uint32 uLenPacket)
{
	// Verify packet is expected size
	if (uLenPacket < 37)
	{
		CString strError;
		strError.Format(_T("***NOTE: Received wrong size (%u) packet in %hs"), uLenPacket, __FUNCTION__);
		throw strError;
	}

	// What search does this relate to
	CByteIO byteIO(pbyPacketData, uLenPacket);
	CUInt128 uTarget;
	byteIO.ReadUInt128(&uTarget);

	// How many results.. Not supported yet..
	uint16 uCount = byteIO.ReadUInt16();
	CUInt128 uAnswer;
	while( uCount > 0 )
	{
		// What is the answer
		byteIO.ReadUInt128(&uAnswer);

		// Get info about answer
		// NOTE: this is the one and only place in Kad where we allow string conversion to local code page in
		// case we did not receive an UTF8 string. this is for backward compatibility for search results which are
		// supposed to be 'viewed' by user only and not feed into the Kad engine again!
		// If that tag list is once used for something else than for viewing, special care has to be taken for any
		// string conversion!
		TagList* pTags = new TagList;
		try
		{
			byteIO.ReadTagList(pTags, true);
		}
		catch(...)
		{
			deleteTagListEntries(pTags);
			delete pTags;
			pTags = NULL;
			throw;
		}
		CSearchManager::ProcessResult(uTarget, uAnswer, pTags);
		uCount--;

⌨️ 快捷键说明

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