📄 kademliaudplistener.cpp
字号:
}
ContactList *pResults = new ContactList;
CUInt128 uIDResult;
try
{
for (uint8 iIndex=0; iIndex<uNumContacts; iIndex++)
{
fileIO.ReadUInt128(&uIDResult);
uint32 uIPResult = fileIO.ReadUInt32();
uint16 uUDPPortResult = fileIO.ReadUInt16();
uint16 uTCPPortResult = fileIO.ReadUInt16();
uint8 uVersion = fileIO.ReadUInt8();
if(::IsGoodIPPort(ntohl(uIPResult),uUDPPortResult))
{
pRoutingZone->Add(uIDResult, uIPResult, uUDPPortResult, uTCPPortResult, uVersion);
pResults->push_back(new CContact(uIDResult, uIPResult, uUDPPortResult, uTCPPortResult, uTarget, uVersion));
}
}
}
catch(...)
{
delete pResults;
throw;
}
CSearchManager::ProcessResponse(uTarget, uIP, uUDPPort, pResults);
}
void CKademliaUDPListener::Free(SSearchTerm* pSearchTerms)
{
if(pSearchTerms)
{
if (pSearchTerms->m_pLeft)
Free(pSearchTerms->m_pLeft);
if (pSearchTerms->m_pRight)
Free(pSearchTerms->m_pRight);
delete pSearchTerms;
}
}
static void TokenizeOptQuotedSearchTerm(LPCTSTR pszString, CStringWArray* lst)
{
LPCTSTR pch = pszString;
while (*pch != _T('\0'))
{
if (*pch == _T('\"'))
{
// Start of quoted string found. If there is no terminating quote character found,
// the start quote character is just skipped. If the quoted string is empty, no
// new entry is added to 'list'.
//
pch++;
LPCTSTR pchNextQuote = _tcschr(pch, _T('\"'));
if (pchNextQuote)
{
size_t nLenQuoted = pchNextQuote - pch;
if (nLenQuoted)
lst->Add(CString(pch, nLenQuoted));
pch = pchNextQuote + 1;
}
}
else
{
// Search for next delimiter or quote character
//
size_t nNextDelimiter = _tcscspn(pch, _T(INV_KAD_KEYWORD_CHARS) _T("\""));
if (nNextDelimiter)
{
lst->Add(CString(pch, nNextDelimiter));
pch += nNextDelimiter;
if (*pch == _T('\0'))
break;
if (*pch == _T('\"'))
continue;
}
pch++;
}
}
}
static CString* _pstrDbgSearchExpr;
SSearchTerm* CKademliaUDPListener::CreateSearchExpressionTree(CSafeMemFile& fileIO, int iLevel)
{
// the max. depth has to match our own limit for creating the search expression
// (see also 'ParsedSearchExpression' and 'GetSearchPacket')
if (iLevel >= 24)
{
AddDebugLogLine(false, _T("***NOTE: Search expression tree exceeds depth limit!"));
return NULL;
}
iLevel++;
uint8 uOp = fileIO.ReadUInt8();
if (uOp == 0x00)
{
uint8 uBoolOp = fileIO.ReadUInt8();
if (uBoolOp == 0x00) // AND
{
SSearchTerm* pSearchTerm = new SSearchTerm;
pSearchTerm->m_type = SSearchTerm::AND;
if (_pstrDbgSearchExpr)
_pstrDbgSearchExpr->Append(_T(" AND"));
if ((pSearchTerm->m_pLeft = CreateSearchExpressionTree(fileIO, iLevel)) == NULL)
{
ASSERT(0);
delete pSearchTerm;
return NULL;
}
if ((pSearchTerm->m_pRight = CreateSearchExpressionTree(fileIO, iLevel)) == NULL)
{
ASSERT(0);
Free(pSearchTerm->m_pLeft);
delete pSearchTerm;
return NULL;
}
return pSearchTerm;
}
else if (uBoolOp == 0x01) // OR
{
SSearchTerm* pSearchTerm = new SSearchTerm;
pSearchTerm->m_type = SSearchTerm::OR;
if (_pstrDbgSearchExpr)
_pstrDbgSearchExpr->Append(_T(" OR"));
if ((pSearchTerm->m_pLeft = CreateSearchExpressionTree(fileIO, iLevel)) == NULL)
{
ASSERT(0);
delete pSearchTerm;
return NULL;
}
if ((pSearchTerm->m_pRight = CreateSearchExpressionTree(fileIO, iLevel)) == NULL)
{
ASSERT(0);
Free(pSearchTerm->m_pLeft);
delete pSearchTerm;
return NULL;
}
return pSearchTerm;
}
else if (uBoolOp == 0x02) // NOT
{
SSearchTerm* pSearchTerm = new SSearchTerm;
pSearchTerm->m_type = SSearchTerm::NOT;
if (_pstrDbgSearchExpr)
_pstrDbgSearchExpr->Append(_T(" NOT"));
if ((pSearchTerm->m_pLeft = CreateSearchExpressionTree(fileIO, iLevel)) == NULL)
{
ASSERT(0);
delete pSearchTerm;
return NULL;
}
if ((pSearchTerm->m_pRight = CreateSearchExpressionTree(fileIO, iLevel)) == NULL)
{
ASSERT(0);
Free(pSearchTerm->m_pLeft);
delete pSearchTerm;
return NULL;
}
return pSearchTerm;
}
else
{
AddDebugLogLine(false, _T("*** Unknown boolean search operator 0x%02x (CreateSearchExpressionTree)"), uBoolOp);
return NULL;
}
}
else if (uOp == 0x01) // String
{
CKadTagValueString str(fileIO.ReadStringUTF8());
KadTagStrMakeLower(str); // make lowercase, the search code expects lower case strings!
if (_pstrDbgSearchExpr)
_pstrDbgSearchExpr->AppendFormat(_T(" \"%ls\""), str);
SSearchTerm* pSearchTerm = new SSearchTerm;
pSearchTerm->m_type = SSearchTerm::String;
pSearchTerm->m_pastr = new CStringWArray;
// pre-tokenize the string term (care about quoted parts)
TokenizeOptQuotedSearchTerm(str, pSearchTerm->m_pastr);
return pSearchTerm;
}
else if (uOp == 0x02) // Meta tag
{
// read tag value
CKadTagValueString strValue(fileIO.ReadStringUTF8());
KadTagStrMakeLower(strValue); // make lowercase, the search code expects lower case strings!
// read tag name
CStringA strTagName;
uint16 lenTagName = fileIO.ReadUInt16();
fileIO.Read(strTagName.GetBuffer(lenTagName), lenTagName);
strTagName.ReleaseBuffer(lenTagName);
SSearchTerm* pSearchTerm = new SSearchTerm;
pSearchTerm->m_type = SSearchTerm::MetaTag;
pSearchTerm->m_pTag = new Kademlia::CKadTagStr(strTagName, strValue);
if (_pstrDbgSearchExpr)
{
if (lenTagName == 1)
_pstrDbgSearchExpr->AppendFormat(_T(" Tag%02X=\"%ls\""), (BYTE)strTagName[0], strValue);
else
_pstrDbgSearchExpr->AppendFormat(_T(" \"%s\"=\"%ls\""), strTagName, strValue);
}
return pSearchTerm;
}
else if (uOp == 0x03 || uOp == 0x08) // Numeric Relation (0x03=32-bit or 0x08=64-bit)
{
static const struct
{
SSearchTerm::ESearchTermType eSearchTermOp;
LPCTSTR pszOp;
}
_aOps[] =
{
{ SSearchTerm::OpEqual, _T("=") }, // mmop=0x00
{ SSearchTerm::OpGreater, _T(">") }, // mmop=0x01
{ SSearchTerm::OpLess, _T("<") }, // mmop=0x02
{ SSearchTerm::OpGreaterEqual, _T(">=") }, // mmop=0x03
{ SSearchTerm::OpLessEqual, _T("<=") }, // mmop=0x04
{ SSearchTerm::OpNotEqual, _T("<>") } // mmop=0x05
};
// read tag value
uint64 ullValue = (uOp == 0x03) ? fileIO.ReadUInt32() : fileIO.ReadUInt64();
// read integer operator
uint8 mmop = fileIO.ReadUInt8();
if (mmop >= ARRSIZE(_aOps))
{
AddDebugLogLine(false, _T("*** Unknown integer search op=0x%02x (CreateSearchExpressionTree)"), mmop);
return NULL;
}
// read tag name
CStringA strTagName;
uint16 uLenTagName = fileIO.ReadUInt16();
fileIO.Read(strTagName.GetBuffer(uLenTagName), uLenTagName);
strTagName.ReleaseBuffer(uLenTagName);
SSearchTerm* pSearchTerm = new SSearchTerm;
pSearchTerm->m_type = _aOps[mmop].eSearchTermOp;
pSearchTerm->m_pTag = new Kademlia::CKadTagUInt64(strTagName, ullValue);
if (_pstrDbgSearchExpr)
{
if (uLenTagName == 1)
_pstrDbgSearchExpr->AppendFormat(_T(" Tag%02X%s%I64u"), (BYTE)strTagName[0], _aOps[mmop].pszOp, ullValue);
else
_pstrDbgSearchExpr->AppendFormat(_T(" \"%s\"%s%I64u"), strTagName, _aOps[mmop].pszOp, ullValue);
}
return pSearchTerm;
}
else
{
AddDebugLogLine(false, _T("*** Unknown search op=0x%02x (CreateSearchExpressionTree)"), uOp);
return NULL;
}
}
// Used in Kad1.0 only
void CKademliaUDPListener::Process_KADEMLIA_SEARCH_REQ (const byte *pbyPacketData, uint32 uLenPacket, uint32 uIP, uint16 uUDPPort)
{
// Verify packet is expected size
if (uLenPacket < 17)
{
CString strError;
strError.Format(_T("***NOTE: Received wrong size (%u) packet in %hs"), uLenPacket, __FUNCTION__);
throw strError;
}
CSafeMemFile fileIO( pbyPacketData, uLenPacket);
CUInt128 uTarget;
fileIO.ReadUInt128(&uTarget);
uint8 uRestrictive = fileIO.ReadUInt8();
if(uLenPacket == 17 )
{
if(uRestrictive)
CKademlia::GetIndexed()->SendValidSourceResult(uTarget, uIP, uUDPPort, false, 0, 0);
else
CKademlia::GetIndexed()->SendValidKeywordResult(uTarget, NULL, uIP, uUDPPort, true, false, 0);
}
else if(uLenPacket > 17)
{
SSearchTerm* pSearchTerms = NULL;
bool bOldClient = true;
if (uRestrictive)
{
try
{
#if defined(_DEBUG) || defined(USE_DEBUG_DEVICE)
_pstrDbgSearchExpr = (thePrefs.GetDebugServerSearchesLevel() > 0) ? new CString : NULL;
#endif
pSearchTerms = CreateSearchExpressionTree(fileIO, 0);
if (_pstrDbgSearchExpr)
{
Debug(_T("KadSearchTerm=%s\n"), *_pstrDbgSearchExpr);
delete _pstrDbgSearchExpr;
_pstrDbgSearchExpr = NULL;
}
}
catch(...)
{
Free(pSearchTerms);
throw;
}
if (pSearchTerms == NULL)
throw CString(_T("Invalid search expression"));
if(uRestrictive>1)
bOldClient = false;
}
else
bOldClient = false;
//Keyword request with added options.
CKademlia::GetIndexed()->SendValidKeywordResult(uTarget, pSearchTerms, uIP, uUDPPort, bOldClient, false, 0x0000);
Free(pSearchTerms);
}
}
// Used in Kad2.0 only
void CKademliaUDPListener::Process_KADEMLIA2_SEARCH_KEY_REQ (const byte *pbyPacketData, uint32 uLenPacket, uint32 uIP, uint16 uUDPPort)
{
CSafeMemFile fileIO( pbyPacketData, uLenPacket);
CUInt128 uTarget;
fileIO.ReadUInt128(&uTarget);
uint16 uStartPosition = fileIO.ReadUInt16();
bool uRestrictive = ((uStartPosition & 0x8000) == 0x8000);
uStartPosition = uStartPosition & 0x7FFF;
SSearchTerm* pSearchTerms = NULL;
if (uRestrictive)
{
try
{
#if defined(_DEBUG) || defined(USE_DEBUG_DEVICE)
_pstrDbgSearchExpr = (thePrefs.GetDebugServerSearchesLevel() > 0) ? new CString : NULL;
#endif
pSearchTerms = CreateSearchExpressionTree(fileIO, 0);
if (_pstrDbgSearchExpr)
{
Debug(_T("KadSearchTerm=%s\n"), *_pstrDbgSearchExpr);
delete _pstrDbgSearchExpr;
_pstrDbgSearchExpr = NULL;
}
}
catch(...)
{
Free(pSearchTerms);
throw;
}
if (pSearchTerms == NULL)
throw CString(_T("Invalid search expression"));
}
CKademlia::GetIndexed()->SendValidKeywordResult(uTarget, pSearchTerms, uIP, uUDPPort, false, true, uStartPosition);
if(pSearchTerms)
Free(pSearchTerms);
}
// Used in Kad2.0 only
void CKademliaUDPListener::Process_KADEMLIA2_SEARCH_SOURCE_REQ (const byte *pbyPacketData, uint32 uLenPacket, uint32 uIP, uint16 uUDPPort)
{
CSafeMemFile fileIO( pbyPacketData, uLenPacket);
CUInt128 uTarget;
fileIO.ReadUInt128(&uTarget);
uint16 uStartPosition = (fileIO.ReadUInt16() & 0x7FFF);
uint64 uFileSize = fileIO.ReadUInt64();
CKademlia::GetIndexed()->SendValidSourceResult(uTarget, uIP, uUDPPort, true, uStartPosition, uFileSize);
}
// Used in Kad1.0 only
void CKademliaUDPListener::Process_KADEMLIA_SEARCH_RES (const byte *pbyPacketData, uint32 uLenPacket)
{
// Verify packet is expected size
if (uLenPacket < 37)
{
CString strError;
strError.Format(_T("***NOTE: Received wrong size (%u) packet in %hs"), uLenPacket, __FUNCTION__);
throw strError;
}
// What search does this relate to
CByteIO byteIO(pbyPacketData, uLenPacket);
CUInt128 uTarget;
byteIO.ReadUInt128(&uTarget);
// How many results.. Not supported yet..
uint16 uCount = byteIO.ReadUInt16();
CUInt128 uAnswer;
while( uCount > 0 )
{
// What is the answer
byteIO.ReadUInt128(&uAnswer);
// Get info about answer
// NOTE: this is the one and only place in Kad where we allow string conversion to local code page in
// case we did not receive an UTF8 string. this is for backward compatibility for search results which are
// supposed to be 'viewed' by user only and not feed into the Kad engine again!
// If that tag list is once used for something else than for viewing, special care has to be taken for any
// string conversion!
TagList* pTags = new TagList;
try
{
byteIO.ReadTagList(pTags, true);
}
catch(...)
{
deleteTagListEntries(pTags);
delete pTags;
pTags = NULL;
throw;
}
CSearchManager::ProcessResult(uTarget, uAnswer, pTags);
uCount--;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -