📄 search.cpp
字号:
prepareToStop();
break;
}
CSafeMemFile bio(34);
bio.WriteUInt128(&m_target);
if( m_fileIDs.size() != 1)
throw CString(_T("Kademlia.CSearch.processResponse: m_fileIDs.size() != 1"));
bio.WriteUInt128(&m_fileIDs.front());
bio.WriteUInt16(thePrefs.GetPort());
CKademlia::getUDPListener()->sendPacket( &bio, KADEMLIA_FINDSOURCE_REQ, from->getIPAddress(), from->getUDPPort());
m_count++;
theApp.emuledlg->kademliawnd->searchList->SearchRef(this);
break;
}
}
}
}
}
}
catch (...)
{
AddDebugLogLine(false, _T("Exception in CSearch::processResponse"));
}
delete results;
}
void CSearch::processResult(uint32 fromIP, uint16 fromPort, const CUInt128 &answer, TagList *info)
{
switch(m_type)
{
case FILE:
processResultFile(fromIP, fromPort, answer, info);
break;
case KEYWORD:
processResultKeyword(fromIP, fromPort, answer, info);
break;
case NOTES:
processResultNotes(fromIP, fromPort, answer, info);
break;
}
theApp.emuledlg->kademliawnd->searchList->SearchRef(this);
}
void CSearch::processResultFile(uint32 fromIP, uint16 fromPort, const CUInt128 &answer, TagList *info)
{
CString temp;
uint8 type = 0;
uint32 ip = 0;
uint16 tcp = 0;
uint16 udp = 0;
uint32 serverip = 0;
uint16 serverport = 0;
uint32 clientid = 0;
uchar buddyhash[16];
CUInt128 buddy;
CTag *tag;
TagList::const_iterator it;
for (it = info->begin(); it != info->end(); it++)
{
tag = *it;
if (!tag->m_name.Compare(TAG_SOURCETYPE))
type = tag->GetInt();
else if (!tag->m_name.Compare(TAG_SOURCEIP))
ip = tag->GetInt();
else if (!tag->m_name.Compare(TAG_SOURCEPORT))
tcp = tag->GetInt();
else if (!tag->m_name.Compare(TAG_SOURCEUPORT))
udp = tag->GetInt();
else if (!tag->m_name.Compare(TAG_SERVERIP))
serverip = tag->GetInt();
else if (!tag->m_name.Compare(TAG_SERVERPORT))
serverport = tag->GetInt();
else if (!tag->m_name.Compare(TAG_CLIENTLOWID))
clientid = tag->GetInt();
else if (!tag->m_name.Compare(TAG_BUDDYHASH))
{
strmd4(CStringA(tag->GetStr()), buddyhash);
md4cpy(buddy.getDataPtr(), buddyhash);
}
delete tag;
}
delete info;
switch( type )
{
case 1:
case 3:
{
m_count++;
theApp.downloadqueue->KademliaSearchFile(m_searchID, &answer, &buddy, type, ip, tcp, udp, serverip, serverport, clientid);
break;
}
case 2:
{
//Don't use this type, some clients will process it wrong..
break;
}
}
}
void CSearch::processResultNotes(uint32 fromIP, uint16 fromPort, const CUInt128 &answer, TagList *info)
{
CEntry* entry = new CEntry();
entry->keyID.setValue(m_target);
entry->sourceID.setValue(answer);
CTag *tag;
TagList::const_iterator it;
for (it = info->begin(); it != info->end(); it++)
{
tag = *it;
if (!tag->m_name.Compare(TAG_SOURCEIP))
{
entry->ip = tag->GetInt();
delete tag;
}
else if (!tag->m_name.Compare(TAG_SOURCEPORT))
{
entry->tcpport = tag->GetInt();
delete tag;
}
else if (!tag->m_name.Compare(TAG_FILENAME))
{
entry->fileName = tag->GetStr();
delete tag;
}
else if (!tag->m_name.Compare(TAG_DESCRIPTION))
entry->taglist.push_front(tag);
else if (!tag->m_name.Compare(TAG_FILERATING))
entry->taglist.push_front(tag);
else
delete tag;
}
delete info;
uchar fileid[16];
m_target.toByteArray(fileid);
CKnownFile* file = theApp.sharedfiles->GetFileByID(fileid);
if(!file)
file = (CKnownFile*)theApp.downloadqueue->GetFileByID(fileid);
if(file)
{
m_count++;
file->AddNote(entry);
}
}
void CSearch::processResultKeyword(uint32 fromIP, uint16 fromPort, const CUInt128 &answer, TagList *info)
{
bool interested = false;
CString name;
uint32 size = 0;
CString type;
CString format;
CString artist;
CString album;
CString title;
uint32 length = 0;
CString codec;
uint32 bitrate = 0;
uint32 availability = 0;
CTag *tag;
TagList::const_iterator it;
for (it = info->begin(); it != info->end(); it++)
{
tag = *it;
if (!tag->m_name.Compare(TAG_FILENAME))
{
name = tag->GetStr();
if( name != "" )
{
interested = true;
}
}
else if (!tag->m_name.Compare(TAG_FILESIZE))
size = tag->GetInt();
else if (!tag->m_name.Compare(TAG_FILETYPE))
type = tag->GetStr();
else if (!tag->m_name.Compare(TAG_FILEFORMAT))
format = tag->GetStr();
else if (!tag->m_name.Compare(TAG_MEDIA_ARTIST))
artist = tag->GetStr();
else if (!tag->m_name.Compare(TAG_MEDIA_ALBUM))
album = tag->GetStr();
else if (!tag->m_name.Compare(TAG_MEDIA_TITLE))
title = tag->GetStr();
else if (!tag->m_name.Compare(TAG_MEDIA_LENGTH))
length = tag->GetInt();
else if (!tag->m_name.Compare(TAG_MEDIA_BITRATE))
bitrate = tag->GetInt();
else if (!tag->m_name.Compare(TAG_MEDIA_CODEC))
codec = tag->GetStr();
else if (!tag->m_name.Compare(TAG_SOURCES))
{
availability = tag->GetInt();
if( availability > 65500 )
availability = 0;
}
delete tag;
}
delete info;
if( !interested )
return;
// Check that it matches original criteria
// generally this is ok, but with the transition of Kad from ACP to Unicode we may receive 'wrong' results in the next months which are
// actually not 'wrong' (don't ask for a detailed explanation)
//WordList testWords;
//CSearchManager::getWords(name.GetBuffer(0), &testWords);
//
//WordList::const_iterator mine;
//WordList::const_iterator test;
//CStringW keyword;
//for (mine = m_words.begin(); mine != m_words.end(); mine++)
//{
// keyword = *mine;
// interested = false;
// for (test = testWords.begin(); test != testWords.end(); test++)
// {
// if (!keyword.CompareNoCase(*test))
// {
// interested = true;
// break;
// }
// }
// if (!interested)
// return;
//}
if (interested)
{
m_count++;
theApp.searchlist->KademliaSearchKeyword(m_searchID, &answer, name, size, type, 8,
2, TAG_FILEFORMAT, (LPCTSTR)format,
2, TAG_MEDIA_ARTIST, (LPCTSTR)artist,
2, TAG_MEDIA_ALBUM, (LPCTSTR)album,
2, TAG_MEDIA_TITLE, (LPCTSTR)title,
3, TAG_MEDIA_LENGTH, length,
3, TAG_MEDIA_BITRATE, bitrate,
2, TAG_MEDIA_CODEC, (LPCTSTR)codec,
3, TAG_SOURCES, availability);
}
}
void CSearch::sendFindValue(const CUInt128 &check, uint32 ip, uint16 port)
{
try
{
if(m_stoping)
return;
CSafeMemFile bio(33);
switch(m_type){
case NODE:
case NODECOMPLETE:
bio.WriteUInt8(KADEMLIA_FIND_NODE);
break;
case FILE:
case KEYWORD:
case FINDSOURCE:
case NOTES:
bio.WriteUInt8(KADEMLIA_FIND_VALUE);
break;
case FINDBUDDY:
case STOREFILE:
case STOREKEYWORD:
case STORENOTES:
bio.WriteUInt8(KADEMLIA_STORE);
break;
default:
AddDebugLogLine(false, _T("Invalid search type. (CSearch::sendFindValue)"));
return;
}
bio.WriteUInt128(&m_target);
bio.WriteUInt128(&check);
m_countSent++;
theApp.emuledlg->kademliawnd->searchList->SearchRef(this);
if (thePrefs.GetDebugClientKadUDPLevel() > 0)
{
switch(m_type)
{
case NODE:
DebugSend("KadReqFindNode", ip, port);
break;
case NODECOMPLETE:
DebugSend("KadReqFindNodeCompl", ip, port);
break;
case FILE:
DebugSend("KadReqFindFile", ip, port);
break;
case KEYWORD:
DebugSend("KadReqFindKeyw", ip, port);
break;
case STOREFILE:
DebugSend("KadReqStoreFile", ip, port);
break;
case STOREKEYWORD:
DebugSend("KadReqStoreKeyw", ip, port);
break;
case STORENOTES:
DebugSend("KadReqStoreNotes", ip, port);
break;
case NOTES:
DebugSend("KadReqNotes", ip, port);
break;
default:
DebugSend("KadReqUnknown", ip, port);
}
}
CKademlia::getUDPListener()->sendPacket(&bio, KADEMLIA_REQ, ip, port);
}
catch ( CIOException *ioe )
{
AddDebugLogLine( false, _T("Exception in CSearch::sendFindValue (IO error(%i))"), ioe->m_cause);
ioe->Delete();
}
catch (...)
{
AddDebugLogLine(false, _T("Exception in CSearch::sendFindValue"));
}
}
void CSearch::addFileID(const CUInt128& id)
{
m_fileIDs.push_back(id);
}
void CSearch::PreparePacketForTags( CByteIO *bio, CKnownFile *file)
{
try
{
if( file && bio )
{
TagList taglist;
// Name, Size
taglist.push_back(new CTagStr(TAG_FILENAME, file->GetFileName()));
taglist.push_back(new CTagUInt(TAG_FILESIZE, file->GetFileSize()));
taglist.push_back(new CTagUInt(TAG_SOURCES, (uint32)file->m_nCompleteSourcesCount));
// eD2K file type (Audio, Video, ...)
// NOTE: Archives and CD-Images are published with file type "Pro"
CString strED2KFileType(GetED2KFileTypeSearchTerm(GetED2KFileTypeID(file->GetFileName())));
if (!strED2KFileType.IsEmpty())
taglist.push_back(new CTagStr(TAG_FILETYPE, strED2KFileType));
// file format (filename extension)
int iExt = file->GetFileName().ReverseFind(_T('.'));
if (iExt != -1)
{
CString strExt(file->GetFileName().Mid(iExt));
if (!strExt.IsEmpty())
{
strExt = strExt.Mid(1);
if (!strExt.IsEmpty())
taglist.push_back(new CTagStr(TAG_FILEFORMAT, strExt));
}
}
// additional meta data (Artist, Album, Codec, Length, ...)
// only send verified meta data to nodes
if (file->GetMetaDataVer() > 0)
{
static const struct{
uint8 nName;
uint8 nType;
} _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 i = 0; i < ARRSIZE(_aMetaTags); i++)
{
const ::CTag* pTag = file->GetTag(_aMetaTags[i].nName, _aMetaTags[i].nType);
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] = pTag->GetNameID();
szKadTagName[1] = '\0';
if (pTag->IsStr())
taglist.push_back(new CTagStr(szKadTagName, pTag->GetStr()));
else
taglist.push_back(new CTagUInt(szKadTagName, pTag->GetInt()));
}
}
}
bio->writeTagList(taglist);
TagList::const_iterator it;
for (it = taglist.begin(); it != taglist.end(); it++)
delete *it;
}
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_cause);
ioe->Delete();
}
catch (...)
{
AddDebugLogLine(false, _T("Exception in CSearch::PreparePacketForTags"));
}
}
//Can't clean these up until Taglist works with CSafeMemFiles.
void CSearch::PreparePacket(void)
{
try
{
int count = m_fileIDs.size();
uchar fileid[16];
CKnownFile* file = NULL;
if( count > 150 )
count = 150;
if( count > 100 )
{
bio3 = new CByteIO(packet3,sizeof(packet3));
bio3->writeByte(OP_KADEMLIAHEADER);
bio3->writeByte(KADEMLIA_PUBLISH_REQ);
bio3->writeUInt128(m_target);
bio3->writeUInt16(count-100);
while ( count > 100 )
{
count--;
bio3->writeUInt128(m_fileIDs.front());
m_fileIDs.front().toByteArray(fileid);
m_fileIDs.pop_front();
file = theApp.sharedfiles->GetFileByID(fileid);
PreparePacketForTags( bio3, file );
}
}
if( count > 50 )
{
bio2 = new CByteIO(packet2,sizeof(packet2));
bio2->writeByte(OP_KADEMLIAHEADER);
bio2->writeByte(KADEMLIA_PUBLISH_REQ);
bio2->writeUInt128(m_target);
bio2->writeUInt16(count-50);
while ( count > 50 )
{
count--;
bio2->writeUInt128(m_fileIDs.front());
m_fileIDs.front().toByteArray(fileid);
m_fileIDs.pop_front();
file = theApp.sharedfiles->GetFileByID(fileid);
PreparePacketForTags( bio2, file );
}
}
if( count > 0 )
{
bio1 = new CByteIO(packet1,sizeof(packet1));
bio1->writeByte(OP_KADEMLIAHEADER);
bio1->writeByte(KADEMLIA_PUBLISH_REQ);
bio1->writeUInt128(m_target);
bio1->writeUInt16(count);
while ( count > 0 )
{
count--;
bio1->writeUInt128(m_fileIDs.front());
m_fileIDs.front().toByteArray(fileid);
m_fileIDs.pop_front();
file = theApp.sharedfiles->GetFileByID(fileid);
PreparePacketForTags( bio1, file );
}
}
}
catch ( CIOException *ioe )
{
AddDebugLogLine( false, _T("Exception in CSearch::PreparePacket (IO error(%i))"), ioe->m_cause);
ioe->Delete();
}
catch (...)
{
AddDebugLogLine(false, _T("Exception in CSearch::PreparePacket"));
}
}
uint32 CSearch::getNodeLoad() const
{
if( m_totalLoadResponses == 0 )
{
return 0;
}
return m_totalLoad/m_totalLoadResponses;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -