📄 search.cpp
字号:
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 + -