📄 search.cpp
字号:
ASSERT(prefs != NULL);
CSafeMemFile bio(34);
bio.WriteUInt128(&m_target);
bio.WriteUInt128(&prefs->getClientHash());
bio.WriteUInt16(thePrefs.GetPort());
udpListner->sendPacket( &bio, KADEMLIA_FINDBUDDY_REQ, from->getIPAddress(), from->getUDPPort());
m_count++;
theApp.emuledlg->kademliawnd->searchList->SearchRef(this);
break;
}
case FINDSOURCE:
{
if( m_count > SEARCHFINDSOURCE_TOTAL )
{
prepareToStop();
break;
}
CKademliaUDPListener *udpListner = CKademlia::getUDPListener();
ASSERT(udpListner != NULL);
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());
udpListner->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(const CUInt128 &target, uint32 fromIP, uint16 fromPort, const CUInt128 &answer, TagList *info)
{
switch(m_type)
{
case FILE:
processResultFile(target, fromIP, fromPort, answer, info);
break;
case KEYWORD:
processResultKeyword(target, fromIP, fromPort, answer, info);
break;
}
theApp.emuledlg->kademliawnd->searchList->SearchRef(this);
}
void CSearch::processResultFile(const CUInt128 &target, 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::processResultKeyword(const CUInt128 &target, 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_NAME))
{
name = tag->GetStr();
if( name != "" )
{
interested = true;
}
}
else if (!tag->m_name.Compare(TAG_SIZE))
size = tag->GetInt();
else if (!tag->m_name.Compare(TAG_TYPE))
type = tag->GetStr();
else if (!tag->m_name.Compare(TAG_FORMAT))
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_AVAILABILITY))
{
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_FORMAT, (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_AVAILABILITY, availability);
}
}
void CSearch::sendFindValue(const CUInt128 &target, 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:
bio.WriteUInt8(KADEMLIA_FIND_VALUE);
break;
case FINDBUDDY:
case STOREFILE:
case STOREKEYWORD:
bio.WriteUInt8(KADEMLIA_STORE);
break;
default:
AddDebugLogLine(false, _T("Invalid search type. (CSearch::sendFindValue)"));
return;
}
bio.WriteUInt128(&target);
bio.WriteUInt128(&check);
CKademliaUDPListener *udpListner = CKademlia::getUDPListener();
ASSERT(udpListner != NULL);
m_countSent++;
theApp.emuledlg->kademliawnd->searchList->SearchRef(this);
if (thePrefs.GetDebugClientKadUDPLevel() > 0)
{
if (m_type == NODE)
DebugSend("KadReqFindNode", ip, port);
else if (m_type == NODECOMPLETE)
DebugSend("KadReqFindNodeCompl", ip, port);
else if (m_type == FILE)
DebugSend("KadReqFindFile", ip, port);
else if (m_type == KEYWORD)
DebugSend("KadReqFindKeyw", ip, port);
else if (m_type == STOREFILE)
DebugSend("KadReqStoreFile", ip, port);
else
DebugSend("KadReqStoreKeyw", ip, port);
}
udpListner->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_NAME, file->GetFileName()));
taglist.push_back(new CTagUInt(TAG_SIZE, file->GetFileSize()));
taglist.push_back(new CTagUInt(TAG_AVAILABILITY, (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_TYPE, 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_FORMAT, 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"));
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -