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

📄 search.cpp

📁 电驴下载工具eMule0.47aVeryCD的源代码,可作分析测试也可用于P2P软件的开发研究.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
			else
				bFileSize = false;
		}
		else if (!pTag->m_name.Compare(TAG_FILETYPE))
			sType = pTag->GetStr();
		else if (!pTag->m_name.Compare(TAG_FILEFORMAT))
			sFormat = pTag->GetStr();
		else if (!pTag->m_name.Compare(TAG_MEDIA_ARTIST))
			sArtist = pTag->GetStr();
		else if (!pTag->m_name.Compare(TAG_MEDIA_ALBUM))
			sAlbum = pTag->GetStr();
		else if (!pTag->m_name.Compare(TAG_MEDIA_TITLE))
			sTitle = pTag->GetStr();
		else if (!pTag->m_name.Compare(TAG_MEDIA_LENGTH))
			uLength = (uint32)pTag->GetInt();
		else if (!pTag->m_name.Compare(TAG_MEDIA_BITRATE))
			uBitrate = (uint32)pTag->GetInt();
		else if (!pTag->m_name.Compare(TAG_MEDIA_CODEC))
			sCodec = pTag->GetStr();
		else if (!pTag->m_name.Compare(TAG_SOURCES))
		{
			// Some rouge client was setting a invalid availability, just set it to 0
			uAvailability = (uint32)pTag->GetInt();
			if( uAvailability > 65500 )
				uAvailability = 0;
		}
		delete pTag;
	}
	delete plistInfo;

	// If we don't have a valid filename or filesize, drop this keyword.
	if( !bFileName || !bFileSize )
		return;

	// Check that this result matches original criteria
	WordList listTestWords;
	CSearchManager::GetWords(sName, &listTestWords);
	CStringW keyword;
	for (WordList::const_iterator itWordListWords = m_listWords.begin(); itWordListWords != m_listWords.end(); ++itWordListWords)
	{
		keyword = *itWordListWords;
		bool bInterested = false;
		for (WordList::const_iterator itWordListTestWords = listTestWords.begin(); itWordListTestWords != listTestWords.end(); ++itWordListTestWords)
		{
			if (!keyword.CompareNoCase(*itWordListTestWords))
			{
				bInterested = true;
				break;
			}
		}
		if (!bInterested)
			return;
	}

	// Inc the number of answers.
	m_uAnswers++;
	// Update the search in the GUI
	theApp.emuledlg->kademliawnd->searchList->SearchRef(this);
	// Send we keyword to searchlist to be processed.
	// This method is still legacy from the multithreaded Kad, maybe this can be changed for better handling.
	theApp.searchlist->KademliaSearchKeyword(m_uSearchID, &uAnswer, sName, uSize, sType, 8,
		    2, TAG_FILEFORMAT, (LPCTSTR)sFormat,
		    2, TAG_MEDIA_ARTIST, (LPCTSTR)sArtist,
		    2, TAG_MEDIA_ALBUM, (LPCTSTR)sAlbum,
		    2, TAG_MEDIA_TITLE, (LPCTSTR)sTitle,
		    3, TAG_MEDIA_LENGTH, uLength,
		    3, TAG_MEDIA_BITRATE, uBitrate,
		    2, TAG_MEDIA_CODEC, (LPCTSTR)sCodec,
		    3, TAG_SOURCES, uAvailability);
}

void CSearch::SendFindValue(CContact* pContact)
{
	// Found a Node that we think has contacts closer to our target.
	try
	{
		// Make sure we are not in the process of stopping.
		if(m_bStoping)
			return;
		CSafeMemFile fileIO(33);
		// The number of returned contacts is based on the type of search.
		switch(m_uType)
		{
			case NODE:
			case NODECOMPLETE:
				fileIO.WriteUInt8(KADEMLIA_FIND_NODE);
				break;
			case FILE:
			case KEYWORD:
			case FINDSOURCE:
			case NOTES:
				fileIO.WriteUInt8(KADEMLIA_FIND_VALUE);
				break;
			case FINDBUDDY:
			case STOREFILE:
			case STOREKEYWORD:
			case STORENOTES:
				fileIO.WriteUInt8(KADEMLIA_STORE);
				break;
			default:
				AddDebugLogLine(false, _T("Invalid search type. (CSearch::SendFindValue)"));
				return;
		}
		// Put the target we want into the packet.
		fileIO.WriteUInt128(&m_uTarget);
		// Add the ID of the contact we are contacting for sanity checks on the other end.
		fileIO.WriteUInt128(&pContact->GetClientID());
		// Inc the number of packets sent.
		m_uKadPacketSent++;
		// Update the search for the GUI.
		theApp.emuledlg->kademliawnd->searchList->SearchRef(this);

		/*if(pContact->GetVersion() != 0) // JOHNTODO -- Add ability to switch betweek Kad1.0 and Kad2.0
		{
			CKademlia::GetUDPListener()->SendPacket(&fileIO, KADEMLIA2_REQ, pContact->GetIPAddress(), pContact->GetUDPPort());
			if (thePrefs.GetDebugClientKadUDPLevel() > 0)
			{
				switch(m_uType)
				{
					case NODE:
						DebugSend("KADEMLIA2_REQ(NODE)", pContact->GetIPAddress(), pContact->GetUDPPort());
						break;
					case NODECOMPLETE:
						DebugSend("KADEMLIA2_REQ(NODECOMPLETE)", pContact->GetIPAddress(), pContact->GetUDPPort());
						break;
					case FILE:
						DebugSend("KADEMLIA2_REQ(FILE)", pContact->GetIPAddress(), pContact->GetUDPPort());
						break;
					case KEYWORD:
						DebugSend("KADEMLIA2_REQ(KEYWORD)", pContact->GetIPAddress(), pContact->GetUDPPort());
						break;
					case STOREFILE:
						DebugSend("KADEMLIA2_REQ(STOREFILE)", pContact->GetIPAddress(), pContact->GetUDPPort());
						break;
					case STOREKEYWORD:
						DebugSend("KADEMLIA2_REQ(STOREKEYWORD)", pContact->GetIPAddress(), pContact->GetUDPPort());
						break;
					case STORENOTES:
						DebugSend("KADEMLIA2_REQ(STORENOTES)", pContact->GetIPAddress(), pContact->GetUDPPort());
						break;
					case NOTES:
						DebugSend("KADEMLIA2_REQ(NOTES)", pContact->GetIPAddress(), pContact->GetUDPPort());
						break;
					default:
						DebugSend("KADEMLIA2_REQ()", pContact->GetIPAddress(), pContact->GetUDPPort());
				}
			}
		}
		else*/
		{
			CKademlia::GetUDPListener()->SendPacket(&fileIO, KADEMLIA_REQ, pContact->GetIPAddress(), pContact->GetUDPPort());
			if (thePrefs.GetDebugClientKadUDPLevel() > 0)
			{
				switch(m_uType)
				{
					case NODE:
						DebugSend("KADEMLIA_REQ(NODE)", pContact->GetIPAddress(), pContact->GetUDPPort());
						break;
					case NODECOMPLETE:
						DebugSend("KADEMLIA_REQ(NODECOMPLETE)", pContact->GetIPAddress(), pContact->GetUDPPort());
						break;
					case FILE:
						DebugSend("KADEMLIA_REQ(FILE)", pContact->GetIPAddress(), pContact->GetUDPPort());
						break;
					case KEYWORD:
						DebugSend("KADEMLIA_REQ(KEYWORD)", pContact->GetIPAddress(), pContact->GetUDPPort());
						break;
					case STOREFILE:
						DebugSend("KADEMLIA_REQ(STOREFILE)", pContact->GetIPAddress(), pContact->GetUDPPort());
						break;
					case STOREKEYWORD:
						DebugSend("KADEMLIA_REQ(STOREKEYWORD)", pContact->GetIPAddress(), pContact->GetUDPPort());
						break;
					case STORENOTES:
						DebugSend("KADEMLIA_REQ(STORENOTES)", pContact->GetIPAddress(), pContact->GetUDPPort());
						break;
					case NOTES:
						DebugSend("KADEMLIA_REQ(NOTES)", pContact->GetIPAddress(), pContact->GetUDPPort());
						break;
					default:
						DebugSend("KADEMLIA_REQ()", pContact->GetIPAddress(), pContact->GetUDPPort());
				}
			}
		}
	}
	catch ( CIOException *ioe )
	{
		AddDebugLogLine( false, _T("Exception in CSearch::SendFindValue (IO error(%i))"), ioe->m_iCause);
		ioe->Delete();
	}
	catch (...)
	{
		AddDebugLogLine(false, _T("Exception in CSearch::SendFindValue"));
	}
}

void CSearch::AddFileID(const CUInt128& uID)
{
	// Add a file hash to the search list.
	// This is used mainly for storing keywords, but was also reused for storing notes.
	m_listFileIDs.push_back(uID);
}

void CSearch::PreparePacketForTags( CByteIO *byIO, CKnownFile *pFile)
{
	// We are going to publish a keyword, setup the tag list.
	try
	{
		if( pFile && byIO )
		{
			TagList listTag;

			// Name, Size
			listTag.push_back(new CKadTagStr(TAG_FILENAME, pFile->GetFileName()));
			if(pFile->GetFileSize() > OLD_MAX_EMULE_FILE_SIZE)
			{
				byte byValue[8];
				*((uint64*)byValue) = pFile->GetFileSize();
				listTag.push_back(new CKadTagBsob(TAG_FILESIZE, byValue, sizeof(byValue)));
			}
			else
				listTag.push_back(new CKadTagUInt(TAG_FILESIZE, pFile->GetFileSize()));

			listTag.push_back(new CKadTagUInt(TAG_SOURCES, pFile->m_nCompleteSourcesCount));

			// eD2K file type (Audio, Video, ...)
			// NOTE: Archives and CD-Images are published with file type "Pro"
			CString strED2KFileType(GetED2KFileTypeSearchTerm(GetED2KFileTypeID(pFile->GetFileName())));
			if (!strED2KFileType.IsEmpty())
				listTag.push_back(new CKadTagStr(TAG_FILETYPE, strED2KFileType));

			// file format (filename extension)
			int iExt = pFile->GetFileName().ReverseFind(_T('.'));
			if (iExt != -1)
			{
				CString strExt(pFile->GetFileName().Mid(iExt));
				if (!strExt.IsEmpty())
				{
					strExt = strExt.Mid(1);
					if (!strExt.IsEmpty())
						listTag.push_back(new CKadTagStr(TAG_FILEFORMAT, strExt));
				}
			}

			// additional meta data (Artist, Album, Codec, Length, ...)
			// only send verified meta data to nodes
			if (pFile->GetMetaDataVer() > 0)
			{
				static const struct
				{
					uint8 uName;
					uint8 uType;
				}
				_aMetaTags[] =
				    {
				        { FT_MEDIA_ARTIST,  2 },
				        { FT_MEDIA_ALBUM,   2 },
				        { FT_MEDIA_TITLE,   2 },
				        { FT_MEDIA_LENGTH,  3 },
				        { FT_MEDIA_BITRATE, 3 },
				        { FT_MEDIA_CODEC,   2 }
				    };
				for (int iIndex = 0; iIndex < ARRSIZE(_aMetaTags); iIndex++)
				{
					const ::CTag* pTag = pFile->GetTag(_aMetaTags[iIndex].uName, _aMetaTags[iIndex].uType);
					if (pTag)
					{
						// skip string tags with empty string values
						if (pTag->IsStr() && pTag->GetStr().IsEmpty())
							continue;
						// skip integer tags with '0' values
						if (pTag->IsInt() && pTag->GetInt() == 0)
							continue;
						char szKadTagName[2];
						szKadTagName[0] = (char)pTag->GetNameID();
						szKadTagName[1] = '\0';
						if (pTag->IsStr())
							listTag.push_back(new CKadTagStr(szKadTagName, pTag->GetStr()));
						else
							listTag.push_back(new CKadTagUInt(szKadTagName, pTag->GetInt()));
					}
				}
			}
			byIO->WriteTagList(listTag);
			for (TagList::const_iterator itTagList = listTag.begin(); itTagList != listTag.end(); ++itTagList)
				delete *itTagList;
		}
		else
		{
			//If we get here.. Bad things happen.. Will fix this later if it is a real issue.
			ASSERT(0);
		}
	}
	catch ( CIOException *ioe )
	{
		AddDebugLogLine( false, _T("Exception in CSearch::PreparePacketForTags (IO error(%i))"), ioe->m_iCause);
		ioe->Delete();
	}
	catch (...)
	{
		AddDebugLogLine(false, _T("Exception in CSearch::PreparePacketForTags"));
	}
}

void CSearch::PreparePacket()
{
	// JOHNTODO -- This needs fixed so that it can support Kad2.0..
	// We are setting up packets for a keyword publish.
	try
	{
		// Get the file count as this packet can be split up into set of 50.
		int iCount = m_listFileIDs.size();
		uchar ucharFileid[16];
		// We split up the keywords into 50 per packet.
		// Never send more then 150 keywords or 3 packets.
		if( iCount > 150 )
			iCount = 150;
		if( iCount > 100 )
		{
			pbyIO3 = new CByteIO(byPacket3,sizeof(byPacket3));
			pbyIO3->WriteByte(OP_KADEMLIAHEADER);
			pbyIO3->WriteByte(KADEMLIA_PUBLISH_REQ);
			pbyIO3->WriteUInt128(m_uTarget);
			pbyIO3->WriteUInt16((uint16)(iCount-100));
			while ( iCount > 100 )
			{
				iCount--;
				pbyIO3->WriteUInt128(m_listFileIDs.front());
				m_listFileIDs.front().ToByteArray(ucharFileid);
				m_listFileIDs.pop_front();
				CKnownFile* pFile = theApp.sharedfiles->GetFileByID(ucharFileid);
				PreparePacketForTags( pbyIO3, pFile );
			}
		}
		if( iCount > 50 )
		{
			pbyIO2 = new CByteIO(byPacket2,sizeof(byPacket2));
			pbyIO2->WriteByte(OP_KADEMLIAHEADER);
			pbyIO2->WriteByte(KADEMLIA_PUBLISH_REQ);
			pbyIO2->WriteUInt128(m_uTarget);
			pbyIO2->WriteUInt16((uint16)(iCount-50));
			while ( iCount > 50 )
			{
				iCount--;
				pbyIO2->WriteUInt128(m_listFileIDs.front());
				m_listFileIDs.front().ToByteArray(ucharFileid);
				m_listFileIDs.pop_front();
				CKnownFile* pFile = theApp.sharedfiles->GetFileByID(ucharFileid);
				PreparePacketForTags( pbyIO2, pFile );
			}
		}
		if( iCount > 0 )
		{
			pbyIO1 = new CByteIO(byPacket1,sizeof(byPacket1));
			pbyIO1->WriteByte(OP_KADEMLIAHEADER);
			pbyIO1->WriteByte(KADEMLIA_PUBLISH_REQ);
			pbyIO1->WriteUInt128(m_uTarget);
			pbyIO1->WriteUInt16((uint16)iCount);
			while ( iCount > 0 )
			{
				iCount--;
				pbyIO1->WriteUInt128(m_listFileIDs.front());
				m_listFileIDs.front().ToByteArray(ucharFileid);
				m_listFileIDs.pop_front();
				CKnownFile* pFile = theApp.sharedfiles->GetFileByID(ucharFileid);
				PreparePacketForTags( pbyIO1, pFile );
			}
		}
	}
	catch ( CIOException *ioe )
	{
		AddDebugLogLine( false, _T("Exception in CSearch::PreparePacket (IO error(%i))"), ioe->m_iCause);
		ioe->Delete();
	}
	catch (...)
	{
		AddDebugLogLine(false, _T("Exception in CSearch::PreparePacket"));
	}
}

uint32 CSearch::GetNodeLoad() const
{
	// Node load is the average of all node load responses.
	if( m_uTotalLoadResponses == 0 )
	{
		return 0;
	}
	return m_uTotalLoad/m_uTotalLoadResponses;
}

uint32 CSearch::GetSearchID() const
{
	return m_uSearchID;
}
uint32 CSearch::GetSearchTypes() const
{
	return m_uType;
}
void CSearch::SetSearchTypes( uint32 uVal )
{
	m_uType = uVal;
}
void CSearch::SetTargetID( CUInt128 uVal )
{
	m_uTarget = uVal;
}
uint32 CSearch::GetAnswers() const
{
	// If we sent more then one packet per node, we have to average the answers for the real count.
	if(pbyIO2 == NULL)
		return m_uAnswers;
	else if(pbyIO3 == NULL)
		return m_uAnswers/2;
	else
		return m_uAnswers/3;
}
uint32 CSearch::GetKadPacketSent() const
{
	return m_uKadPacketSent;
}
uint32 CSearch::GetRequestAnswer() const
{
	return m_uTotalRequestAnswers;
}

const CString& CSearch::GetFileName() const
{
	return m_sFileName;
}
void CSearch::SetFileName(const CString& sFileName)
{
	m_sFileName = sFileName;
}
CUInt128 CSearch::GetTarget() const
{
	return m_uTarget;
}
bool CSearch::Stoping() const
{
	return m_bStoping;
}
uint32 CSearch::GetNodeLoadResonse() const
{
	return m_uTotalLoadResponses;
}
uint32 CSearch::GetNodeLoadTotal() const
{
	return m_uTotalLoad;
}
void CSearch::UpdateNodeLoad( uint8 uLoad )
{
	// Since all nodes do not return a load value, keep track of total responses and total load.
	m_uTotalLoad += uLoad;
	m_uTotalLoadResponses++;
}

⌨️ 快捷键说明

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