📄 search.cpp
字号:
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;
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();
delete tag;
}
delete info;
switch( type )
{
case 1:
{
m_count++;
theApp.downloadqueue->KademliaSearchFile(m_searchID, &answer, type, ip, tcp, udp, serverip, serverport, clientid);
break;
}
/* case 2:
{
//Don't use this type, some clients will process it wrong..
break;
}
case 3:
{
//This will be a firewaled client connected to Kad only.
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
WordList testWords;
CSearchManager::getWords(name.GetBuffer(0), &testWords);
WordList::const_iterator mine;
WordList::const_iterator test;
CString keyword;
for (mine = m_words.begin(); mine != m_words.end(); mine++)
{
keyword = *mine;
if (keyword.GetAt(0) == '-')
{
if (type.CompareNoCase(keyword.GetBuffer(0) + 1))
{
interested = false;
break;
}
}
else
{
interested = false;
for (test = testWords.begin(); test != testWords.end(); test++)
{
if (!keyword.CompareNoCase(*test))
{
interested = true;
break;
}
}
}
if (!interested)
return;
}
if (interested)
{
m_count++;
if (format.GetLength() == 0)
{
theApp.searchlist->KademliaSearchKeyword(m_searchID, &answer, name.GetBuffer(0), size, type.GetBuffer(0), 0);
}
else if (length != 0 || !codec.IsEmpty() || bitrate != 0)
{
theApp.searchlist->KademliaSearchKeyword(m_searchID, &answer, name.GetBuffer(0), size, type.GetBuffer(0), 8,
2, TAG_FORMAT, format.GetBuffer(0),
2, TAG_MEDIA_ARTIST, artist,
2, TAG_MEDIA_ALBUM, album,
2, TAG_MEDIA_TITLE, title,
3, TAG_MEDIA_LENGTH, length,
3, TAG_MEDIA_BITRATE, bitrate,
2, TAG_MEDIA_CODEC, codec,
3, TAG_AVAILABILITY, availability);
}
else if ((!type.Compare("Image")) && (artist.GetLength() > 0))
{
theApp.searchlist->KademliaSearchKeyword(m_searchID, &answer, name.GetBuffer(0), size, type.GetBuffer(0), 3,
2, TAG_FORMAT, format.GetBuffer(0),
2, TAG_MEDIA_ARTIST, artist,
3, TAG_AVAILABILITY, availability);
}
else
{
theApp.searchlist->KademliaSearchKeyword(m_searchID, &answer, name.GetBuffer(0), size, type.GetBuffer(0), 2,
2, TAG_FORMAT, format.GetBuffer(0),
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:
bio.WriteUInt8(KADEMLIA_FIND_VALUE);
break;
case STOREFILE:
case STOREKEYWORD:
bio.WriteUInt8(KADEMLIA_STORE);
break;
default:
CKademlia::debugLine("Invalid search type. (CSearch::sendFindValue)");
return;
}
bio.WriteUInt128(&target);
bio.WriteUInt128(&check);
// CKademlia::debugMsg("Sent UDP OpCode KADEMLIA_REQUEST(%u)", ip);
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 )
{
CKademlia::debugMsg("Exception in CSearch::sendFindValue (IO error(%i))", ioe->m_cause);
ioe->Delete();
}
catch (...)
{
CKademlia::debugLine("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, ...)
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->tag.type == 2 && (pTag->tag.stringvalue == NULL || pTag->tag.stringvalue[0] == '\0'))
continue;
// skip integer tags with '0' values
if (pTag->tag.type == 3 && pTag->tag.intvalue == 0)
continue;
char szKadTagName[2];
szKadTagName[0] = pTag->tag.specialtag;
szKadTagName[1] = '\0';
if (pTag->tag.type == 2)
taglist.push_back(new CTagStr(szKadTagName, pTag->tag.stringvalue));
else
taglist.push_back(new CTagUInt(szKadTagName, pTag->tag.intvalue));
}
}
}
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 )
{
CKademlia::debugMsg("Exception in CSearch::PreparePacketForTags (IO error(%i))", ioe->m_cause);
ioe->Delete();
}
catch (...)
{
CKademlia::debugLine("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 )
{
CKademlia::debugMsg("Exception in CSearch::PreparePacket (IO error(%i))", ioe->m_cause);
ioe->Delete();
}
catch (...)
{
CKademlia::debugLine("Exception in CSearch::PreparePacket");
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -