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

📄 kademliaudplistener.cpp

📁 电驴的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//		bool flag3 = (type >> 8); //Reserved

	type = type & 0x1F;
	if( type == 0 )
	{
		CString strError;
		strError.Format(_T("***NOTE: Received wrong type (0x%02x) in %hs"), type, __FUNCTION__);
		throw strError;
	}

	//This is the target node trying to be found.
	CUInt128 target;
	bio.ReadUInt128(&target);
	CUInt128 distance(prefs->getKadID());
	distance.xor(target);

	//This makes sure we are not mistaken identify. Some client may have fresh installed and have a new hash.
	CUInt128 check;
	bio.ReadUInt128(&check);
	if( prefs->getKadID().compareTo(check))
		return;

	// Get required number closest to target
	ContactMap results;
	routingZone->getClosestTo(0, distance, (int)type, &results);
	uint16 count = (uint16)results.size();

	// Write response
	// Max count is 32. size 817.. 
	// 16 + 1 + 25(32)
	CSafeMemFile bio2( 817 );
	bio2.WriteUInt128(&target);
	bio2.WriteUInt8((byte)count);
	CContact *c;
	CUInt128 id;
	ContactMap::const_iterator it;
	for (it = results.begin(); it != results.end(); it++)
	{
		c = it->second;
		c->getClientID(&id);
		bio2.WriteUInt128(&id);
		bio2.WriteUInt32(c->getIPAddress());
		bio2.WriteUInt16(c->getUDPPort());
		bio2.WriteUInt16(c->getTCPPort());
		bio2.WriteUInt8(c->getType());
	}

	if (thePrefs.GetDebugClientKadUDPLevel() > 0)
		DebugSendF("KadRes", ip, port, _T("Count=%u"), count);

	sendPacket(&bio2, KADEMLIA_RES, ip, port);
}

//KADEMLIA_RES
void CKademliaUDPListener::processKademliaResponse (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port)
{
	// Verify packet is expected size
	if (lenPacket < 17){
		CString strError;
		strError.Format(_T("***NOTE: Received wrong size (%u) packet in %hs"), lenPacket, __FUNCTION__);
		throw strError;
	}

	//Used Pointers
	CPrefs *prefs = CKademlia::getPrefs();
	ASSERT(prefs != NULL); 
	CRoutingZone *routingZone = CKademlia::getRoutingZone();
	ASSERT(routingZone != NULL); 

	if(prefs->getRecheckIP())
	{
		firewalledCheck(ip, port);
		if (thePrefs.GetDebugClientKadUDPLevel() > 0)
			DebugSend("KadHelloReq", ip, port);
		sendMyDetails(KADEMLIA_HELLO_REQ, ip, port);
	}

	// What search does this relate to
	CSafeMemFile bio( packetData, lenPacket);
	CUInt128 target;
	bio.ReadUInt128(&target);
	uint16 numContacts = bio.ReadUInt8();

	// Verify packet is expected size
	if (lenPacket != 16+1 + (16+4+2+2+1)*numContacts){
		CString strError;
		strError.Format(_T("***NOTE: Received wrong size (%u) packet in %hs"), lenPacket, __FUNCTION__);
		throw strError;
	}

	// Set contact to alive.
	routingZone->setAlive(ip, port);

	CUInt128 id;
	ContactList *results = new ContactList;
	try
	{
		for (uint16 i=0; i<numContacts; i++)
		{
			bio.ReadUInt128(&id);
			uint32 ip = bio.ReadUInt32();
			uint16 port = bio.ReadUInt16();
			uint16 tport = bio.ReadUInt16();
			byte type = bio.ReadUInt8();
			if(::IsGoodIPPort(ntohl(ip),port))
			{
				routingZone->add(id, ip, port, tport, type);
				results->push_back(new CContact(id, ip, port, tport, type, target));
			}
		}
	}
	catch(...)
	{
		delete results;
		throw;
	}
	CSearchManager::processResponse(target, ip, port, results);
}

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

SSearchTerm* CKademliaUDPListener::CreateSearchExpressionTree(CSafeMemFile& bio, 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 op = bio.ReadUInt8();
	if (op == 0x00)
	{
		uint8 boolop = bio.ReadUInt8();
		if (boolop == 0x00) // AND
		{
			SSearchTerm* pSearchTerm = new SSearchTerm;
			pSearchTerm->type = SSearchTerm::AND;
			TRACE(" AND");
			if ((pSearchTerm->left = CreateSearchExpressionTree(bio, iLevel)) == NULL){
				ASSERT(0);
				delete pSearchTerm;
				return NULL;
			}
			if ((pSearchTerm->right = CreateSearchExpressionTree(bio, iLevel)) == NULL){
				ASSERT(0);
				Free(pSearchTerm->left);
				delete pSearchTerm;
				return NULL;
			}
			return pSearchTerm;
		}
		else if (boolop == 0x01) // OR
		{
			SSearchTerm* pSearchTerm = new SSearchTerm;
			pSearchTerm->type = SSearchTerm::OR;
			TRACE(" OR");
			if ((pSearchTerm->left = CreateSearchExpressionTree(bio, iLevel)) == NULL){
				ASSERT(0);
				delete pSearchTerm;
				return NULL;
			}
			if ((pSearchTerm->right = CreateSearchExpressionTree(bio, iLevel)) == NULL){
				ASSERT(0);
				Free(pSearchTerm->left);
				delete pSearchTerm;
				return NULL;
			}
			return pSearchTerm;
		}
		else if (boolop == 0x02) // NAND
		{
			SSearchTerm* pSearchTerm = new SSearchTerm;
			pSearchTerm->type = SSearchTerm::NAND;
			TRACE(" NAND");
			if ((pSearchTerm->left = CreateSearchExpressionTree(bio, iLevel)) == NULL){
				ASSERT(0);
				delete pSearchTerm;
				return NULL;
			}
			if ((pSearchTerm->right = CreateSearchExpressionTree(bio, iLevel)) == NULL){
				ASSERT(0);
				Free(pSearchTerm->left);
				delete pSearchTerm;
				return NULL;
			}
			return pSearchTerm;
		}
		else{
			AddDebugLogLine(false, _T("*** Unknown boolean search operator 0x%02x (CreateSearchExpressionTree)"), boolop);
			return NULL;
		}
	}
	else if (op == 0x01) // String
	{
		CTagValueString str(bio.ReadStringUTF8());

		KadTagStrMakeLower(str); // make lowercase, the search code expects lower case strings!
		TRACE(" \"%ls\"", str);

		SSearchTerm* pSearchTerm = new SSearchTerm;
		pSearchTerm->type = SSearchTerm::String;
		pSearchTerm->astr = new CStringWArray;

		// pre-tokenize the string term
		int iPosTok = 0;
		CTagValueString strTok(str.Tokenize(_awszInvKadKeywordChars, iPosTok));
		while (!strTok.IsEmpty())
		{
			pSearchTerm->astr->Add(strTok);
			strTok = str.Tokenize(_awszInvKadKeywordChars, iPosTok);
		}

		return pSearchTerm;
	}
	else if (op == 0x02) // Meta tag
	{
		// read tag value
		CTagValueString strValue(bio.ReadStringUTF8());

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

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

		SSearchTerm* pSearchTerm = new SSearchTerm;
		pSearchTerm->type = SSearchTerm::MetaTag;
		pSearchTerm->tag = new Kademlia::CTagStr(strTagName, strValue);
		if (lenTagName == 1)
			TRACE(" Tag%02x=\"%ls\"", strTagName[0], strValue);
		else
			TRACE(" \"%s\"=\"%ls\"", strTagName, strValue);
		return pSearchTerm;
	}
	else if (op == 0x03) // Min/Max
	{
		static const struct {
			SSearchTerm::ESearchTermType eSearchTermOp;
			LPCSTR pszOp;
		} _aOps[] =
		{
			{ SSearchTerm::OpEqual,			"="		}, // mmop=0x00
			{ SSearchTerm::OpGreaterEqual,	">="	}, // mmop=0x01
			{ SSearchTerm::OpLessEqual,		"<="	}, // mmop=0x02
			{ SSearchTerm::OpGreater,		">"		}, // mmop=0x03
			{ SSearchTerm::OpLess,			"<"		}, // mmop=0x04
			{ SSearchTerm::OpNotEqual,		"!="	}  // mmop=0x05
		};

		// read tag value
		uint32 uValue = bio.ReadUInt32();

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

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

		SSearchTerm* pSearchTerm = new SSearchTerm;
		pSearchTerm->type = _aOps[mmop].eSearchTermOp;
		pSearchTerm->tag = new Kademlia::CTagUInt32(strTagName, uValue);

		if (lenTagName == 1)
			TRACE(" Tag%02x%s%u", (BYTE)strTagName[0], _aOps[mmop].pszOp, uValue);
		else
			TRACE(" \"%s\"%s%u", strTagName, _aOps[mmop].pszOp, uValue);

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

//KADEMLIA_SEARCH_REQ
void CKademliaUDPListener::processSearchRequest (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port)
{
	// Verify packet is expected size
	if (lenPacket < 17){
		CString strError;
		strError.Format(_T("***NOTE: Received wrong size (%u) packet in %hs"), lenPacket, __FUNCTION__);
		throw strError;
	}

	//Used Pointers
	CIndexed *indexed = CKademlia::getIndexed();
	ASSERT(indexed != NULL); 

	CSafeMemFile bio( packetData, lenPacket);
	CUInt128 target;
	bio.ReadUInt128(&target);
	uint8 restrictive = bio.ReadUInt8();

#ifdef _DEBUG
	DWORD dwNow = GetTickCount();
#endif
	if(lenPacket == 17 )
	{
		if(restrictive)
		{
			//Source request
			indexed->SendValidSourceResult(target, ip, port);
			//DEBUG_ONLY( Debug("SendValidSourceResult: Time=%.2f sec\n", (GetTickCount() - dwNow) / 1000.0) );
		}
		else
		{
			//Single keyword request
			indexed->SendValidKeywordResult(target, NULL, ip, port );
			//DEBUG_ONLY( Debug("SendValidKeywordResult (Single): Time=%.2f sec\n", (GetTickCount() - dwNow) / 1000.0) );
		}
	}
	else if(lenPacket > 17)
	{
		SSearchTerm* pSearchTerms = NULL;
		if (restrictive)
		{
			try
			{
				pSearchTerms = CreateSearchExpressionTree(bio, 0);
				TRACE("\n");
			}
			catch(...)
			{
				Free(pSearchTerms);
				throw;
			}
		}
		//Keyword request with added options.
		indexed->SendValidKeywordResult(target, pSearchTerms, ip, port); 
		Free(pSearchTerms);
		//DEBUG_ONLY( Debug("SendValidKeywordResult: Time=%.2f sec\n", (GetTickCount() - dwNow) / 1000.0) );
	}
}

//KADEMLIA_SEARCH_RES
void CKademliaUDPListener::processSearchResponse (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port)
{
	// Verify packet is expected size
	if (lenPacket < 37){
		CString strError;
		strError.Format(_T("***NOTE: Received wrong size (%u) packet in %hs"), lenPacket, __FUNCTION__);
		throw strError;
	}

	//Used Pointers
	CRoutingZone *routingZone = CKademlia::getRoutingZone();
	ASSERT(routingZone != NULL); 

	// Set contact to alive.
	routingZone->setAlive(ip, port);

	// What search does this relate to
	CByteIO bio(packetData, lenPacket);
	CUInt128 target;
	bio.readUInt128(&target);

	// How many results.. Not supported yet..
	uint16 count = bio.readUInt16();
	while( count > 0 )
	{
		// What is the answer
		CUInt128 answer;
		bio.readUInt128(&answer);

		// 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 *tags = bio.readTagList(true/*bOptACP*/);
		CSearchManager::processResult(target, ip, port, answer,tags);
		count--;
	}
}

//KADEMLIA_PUBLISH_REQ
void CKademliaUDPListener::processPublishRequest (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port)
{
	//There are different types of publishing..
	//Keyword and File are Stored..
	// Verify packet is expected size
	if (lenPacket < 37){
		CString strError;
		strError.Format(_T("***NOTE: Received wrong size (%u) packet in %hs"), lenPacket, __FUNCTION__);
		throw strError;
	}

	//Used Pointers
	CIndexed *indexed = CKademlia::getIndexed();
	ASSERT(indexed != NULL);
	CPrefs *prefs = CKademlia::getPrefs();
	ASSERT(prefs != NULL); 

	if( prefs->getFirewalled() )
		//We are firewalled. We should not index this entry and give publisher a false report.
		return;

	CByteIO bio(packetData, lenPacket);
	CUInt128 file;
	bio.readUInt128(&file);

	CUInt128 distance;
	prefs->getKadID(&distance);
	distance.xor(file);

	if( thePrefs.FilterLANIPs() && distance.get32BitChunk(0) > SEARCHTOLERANCE)
		return;

	bool bDbgInfo = thePrefs.GetDebugClientKadUDPLevel() > 0;
	CString strInfo;
	uint16 count = bio.readUInt16();
	bool flag = false;
	uint8 load = 0;
	while( count > 0 )
	{
		strInfo.Empty();

		CUInt128 target;
		bio.readUInt128(&target);

		Kademlia::CEntry* entry = new Kademlia::CEntry();
		try
		{
			entry->ip = ip;
			entry->udpport = port;
			entry->keyID.setValue(file);
			entry->sourceID.setValue(target);
			uint32 tags = bio.readByte();
			while(tags > 0)
			{
				CTag* tag = bio.readTag();
				if(tag)
				{
					if (!tag->m_name.Compare(TAG_SOURCETYPE) && tag->m_type == 9)
					{
						if( entry->source == false )
						{
							entry->taglist.push_back(new CTagUInt32(TAG_SOURCEIP, entry->ip));
							entry->taglist.push_back(new CTagUInt16(TAG_SOURCEUPORT, entry->udpport));
						}
						else
						{
							//More then one sourcetype tag found.
							delete tag;
						}
						entry->source = true;
					}
					
					if (!tag->m_name.Compare(TAG_NAME))
					{
						if ( entry->fileName.IsEmpty() )
						{
							entry->fileName = tag->GetStr();
							KadTagStrMakeLower(entry->fileName); // make lowercase, the search code expects lower case strings!
							if (bDbgInfo)
								strInfo.AppendFormat(_T("  Name=\"%ls\""), entry->fileName);
							// NOTE: always add the 'name' tag, even if it's stored separately in 'fileName'. the tag is still needed for answering search request
							entry->taglist.push_back(tag);
						}
						else
						{
							//More then one Name tag found.
							delete tag;
						}
					}
					else if (!tag->m_name.Compare(TAG_SIZE))
					{
						if( entry->size == 0 )
						{
							entry->size = tag->GetInt();
							if (bDbgInfo)
								strInfo.AppendFormat(_T("  Size=%u"), entry->size);
							// NOTE: always add the 'size' tag, even if it's stored separately in 'size'. the tag is still needed for answering search request
							entry->taglist.push_back(tag);

⌨️ 快捷键说明

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