📄 kademliaudplistener.cpp
字号:
if (lenPacket != (2 + 25*numContacts))
return;
// Add these contacts to the list.
addContacts(packetData+2, lenPacket-2, numContacts);
// Send sender to alive.
routingZone->setAlive(ip, port);
}
//KADEMLIA_HELLO_REQ
void CKademliaUDPListener::processHelloRequest (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port)
{
// Verify packet is expected size
if (lenPacket != 25){
CString strError;
strError.Format("***NOTE: Received wrong size (%u) packet in %s", lenPacket, __FUNCTION__);
throw strError;
}
//Used Pointers
CPrefs *prefs = CKademlia::getPrefs();
ASSERT(prefs != NULL);
// Add the sender to the list of contacts
addContact(packetData, lenPacket, ip, port);
// Send response
if (thePrefs.GetDebugClientKadUDPLevel() > 0)
DebugSend("KadHelloRes", ip, port);
sendMyDetails(KADEMLIA_HELLO_RES, ip, port);
// Check if firewalled
if(prefs->getRecheckIP())
{
firewalledCheck(ip, port);
}
}
//KADEMLIA_HELLO_RES
void CKademliaUDPListener::processHelloResponse (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port)
{
// Verify packet is expected size
if (lenPacket != 25){
CString strError;
strError.Format("***NOTE: Received wrong size (%u) packet in %s", lenPacket, __FUNCTION__);
throw strError;
}
//Used Pointers
CRoutingZone *routingZone = CKademlia::getRoutingZone();
ASSERT(routingZone != NULL);
// Add or Update contact.
addContact(packetData, lenPacket, ip, port);
// Set contact to alive.
routingZone->setAlive(ip, port);
}
//KADEMLIA_REQ
void CKademliaUDPListener::processKademliaRequest (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port)
{
// Verify packet is expected size
if (lenPacket != 33){
CString strError;
strError.Format("***NOTE: Received wrong size (%u) packet in %s", lenPacket, __FUNCTION__);
throw strError;
}
//Used Pointers
CPrefs *prefs = CKademlia::getPrefs();
ASSERT(prefs != NULL);
CRoutingZone *routingZone = CKademlia::getRoutingZone();
ASSERT(routingZone != NULL);
//RecheckIP and firewall status
if(prefs->getRecheckIP())
{
firewalledCheck(ip, port);
if (thePrefs.GetDebugClientKadUDPLevel() > 0)
DebugSend("KadHelloReq", ip, port);
sendMyDetails(KADEMLIA_HELLO_REQ, ip, port);
}
// Get target and type
CSafeMemFile bio( packetData, lenPacket);
byte type = bio.ReadUInt8();
// bool flag1 = (type >> 6); //Reserved
// bool flag2 = (type >> 7); //Reserved
// bool flag3 = (type >> 8); //Reserved
type = type & 0x1F;
if( type == 0 )
{
CString strError;
strError.Format("***NOTE: Received wrong type (0x%02x) in %s", type, __FUNCTION__);
throw strError;
}
//This is the target node trying to be found.
CUInt128 target;
bio.ReadUInt128(&target);
CUInt128 distance(prefs->getClientID());
distance.xor(target);
//This makes sure we are not mistaken identify. Some client may have fresh installed and have a new hash.
CUInt128 check;
bio.ReadUInt128(&check);
if( prefs->getClientID().compareTo(check))
return;
// Get required number closest to target
ContactMap results;
routingZone->getClosestTo(0, distance, (int)type, &results);
uint16 count = (uint16)results.size();
// Write response
// Max count is 32. size 817..
// 16 + 1 + 25(32)
CSafeMemFile bio2( 817 );
bio2.WriteUInt128(&target);
bio2.WriteUInt8((byte)count);
CContact *c;
CUInt128 id;
ContactMap::const_iterator it;
for (it = results.begin(); it != results.end(); it++)
{
c = it->second;
c->getClientID(&id);
bio2.WriteUInt128(&id);
bio2.WriteUInt32(c->getIPAddress());
bio2.WriteUInt16(c->getUDPPort());
bio2.WriteUInt16(c->getTCPPort());
bio2.WriteUInt8(c->getType());
}
if (thePrefs.GetDebugClientKadUDPLevel() > 0)
DebugSendF("KadRes", ip, port, "Count=%u", count);
sendPacket(&bio2, KADEMLIA_RES, ip, port);
}
//KADEMLIA_RES
void CKademliaUDPListener::processKademliaResponse (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port)
{
// Verify packet is expected size
if (lenPacket < 17){
CString strError;
strError.Format("***NOTE: Received wrong size (%u) packet in %s", lenPacket, __FUNCTION__);
throw strError;
}
//Used Pointers
CPrefs *prefs = CKademlia::getPrefs();
ASSERT(prefs != NULL);
CRoutingZone *routingZone = CKademlia::getRoutingZone();
ASSERT(routingZone != NULL);
if(prefs->getRecheckIP())
{
firewalledCheck(ip, port);
if (thePrefs.GetDebugClientKadUDPLevel() > 0)
DebugSend("KadHelloReq", ip, port);
sendMyDetails(KADEMLIA_HELLO_REQ, ip, port);
}
// What search does this relate to
CSafeMemFile bio( packetData, lenPacket);
CUInt128 target;
bio.ReadUInt128(&target);
uint16 numContacts = bio.ReadUInt8();
// Verify packet is expected size
if (lenPacket != 16+1 + (16+4+2+2+1)*numContacts){
CString strError;
strError.Format("***NOTE: Received wrong size (%u) packet in %s", lenPacket, __FUNCTION__);
throw strError;
}
// Set contact to alive.
routingZone->setAlive(ip, port);
CUInt128 id;
ContactList *results = new ContactList;
try
{
for (uint16 i=0; i<numContacts; i++)
{
bio.ReadUInt128(&id);
uint32 ip = bio.ReadUInt32();
uint16 port = bio.ReadUInt16();
uint16 tport = bio.ReadUInt16();
byte type = bio.ReadUInt8();
if(::IsGoodIPPort(ntohl(ip),port))
{
routingZone->add(id, ip, port, tport, type);
results->push_back(new CContact(id, ip, port, tport, type, target));
}
}
}
catch(...)
{
delete results;
throw;
}
CSearchManager::processResponse(target, ip, port, results);
}
void Free(SSearchTerm* pSearchTerms)
{
if (pSearchTerms->left)
Free(pSearchTerms->left);
if (pSearchTerms->right)
Free(pSearchTerms->right);
delete pSearchTerms;
}
SSearchTerm* CreateSearchExpressionTree(CSafeMemFile& bio, int iLevel)
{
// the max. depth has to match our own limit for creating the search expression
// (see also 'ParsedSearchExpression' and 'GetSearchPacket')
if (iLevel >= 24){
CKademlia::debugLine("***NOTE: Search expression tree exceeds depth limit!");
return NULL;
}
iLevel++;
uint8 op = bio.ReadUInt8();
if (op == 0x00)
{
uint8 boolop = bio.ReadUInt8();
if (boolop == 0x00) // AND
{
SSearchTerm* pSearchTerm = new SSearchTerm;
pSearchTerm->type = SSearchTerm::AND;
TRACE(" AND");
if ((pSearchTerm->left = CreateSearchExpressionTree(bio, iLevel)) == NULL){
ASSERT(0);
delete pSearchTerm;
return NULL;
}
if ((pSearchTerm->right = CreateSearchExpressionTree(bio, iLevel)) == NULL){
ASSERT(0);
Free(pSearchTerm->left);
delete pSearchTerm;
return NULL;
}
return pSearchTerm;
}
else if (boolop == 0x01) // OR
{
SSearchTerm* pSearchTerm = new SSearchTerm;
pSearchTerm->type = SSearchTerm::OR;
TRACE(" OR");
if ((pSearchTerm->left = CreateSearchExpressionTree(bio, iLevel)) == NULL){
ASSERT(0);
delete pSearchTerm;
return NULL;
}
if ((pSearchTerm->right = CreateSearchExpressionTree(bio, iLevel)) == NULL){
ASSERT(0);
Free(pSearchTerm->left);
delete pSearchTerm;
return NULL;
}
return pSearchTerm;
}
else if (boolop == 0x02) // NAND
{
SSearchTerm* pSearchTerm = new SSearchTerm;
pSearchTerm->type = SSearchTerm::NAND;
TRACE(" NAND");
if ((pSearchTerm->left = CreateSearchExpressionTree(bio, iLevel)) == NULL){
ASSERT(0);
delete pSearchTerm;
return NULL;
}
if ((pSearchTerm->right = CreateSearchExpressionTree(bio, iLevel)) == NULL){
ASSERT(0);
Free(pSearchTerm->left);
delete pSearchTerm;
return NULL;
}
return pSearchTerm;
}
else{
CKademlia::debugMsg("*** Unknown boolean search operator 0x%02x (CreateSearchExpressionTree)", boolop);
return NULL;
}
}
else if (op == 0x01) // String
{
uint16 len = bio.ReadUInt16();
CString str;
bio.Read(str.GetBuffer(len), len);
str.ReleaseBuffer(len);
SSearchTerm* pSearchTerm = new SSearchTerm;
pSearchTerm->type = SSearchTerm::String;
pSearchTerm->astr = new CStringArray;
str.MakeLower(); // make lowercase, the search code expects lower case strings!
TRACE(" \"%s\"", str);
// pre-tokenize the string term
int iPosTok = 0;
CString strTok(str.Tokenize(" ()[]{}<>,._-!?", iPosTok));
while (!strTok.IsEmpty())
{
pSearchTerm->astr->Add(strTok);
strTok = str.Tokenize(" ()[]{}<>,._-!?", iPosTok);
}
return pSearchTerm;
}
else if (op == 0x02) // Meta tag
{
// read tag value
CString strValue;
uint16 lenValue = bio.ReadUInt16();
bio.Read(strValue.GetBuffer(lenValue), lenValue);
strValue.ReleaseBuffer(lenValue);
strValue.MakeLower(); // make lowercase, the search code expects lower case strings!
// read tag name
CString strTagName;
uint16 lenTagName = bio.ReadUInt16();
bio.Read(strTagName.GetBuffer(lenTagName), lenTagName);
strTagName.ReleaseBuffer(lenTagName);
SSearchTerm* pSearchTerm = new SSearchTerm;
pSearchTerm->type = SSearchTerm::MetaTag;
pSearchTerm->tag = new Kademlia::CTagStr(strTagName, strValue);
if (lenTagName == 1)
TRACE(" Tag%02x=\"%s\"", strTagName[0], strValue);
else
TRACE(" \"%s\"=\"%s\"", strTagName, strValue);
return pSearchTerm;
}
else if (op == 0x03) // Min/Max
{
static const struct {
SSearchTerm::ESearchTermType eSearchTermOp;
LPCTSTR pszOp;
} _aOps[] =
{
{ SSearchTerm::OpEqual, "=" }, // mmop=0x00
{ SSearchTerm::OpGreaterEqual, ">=" }, // mmop=0x01
{ SSearchTerm::OpLessEqual, "<=" }, // mmop=0x02
{ SSearchTerm::OpGreater, ">" }, // mmop=0x03
{ SSearchTerm::OpLess, "<" }, // mmop=0x04
{ SSearchTerm::OpNotEqual, "!=" } // mmop=0x05
};
// read tag value
uint32 uValue = bio.ReadUInt32();
// read integer operator
uint8 mmop = bio.ReadUInt8();
if (mmop >= ARRSIZE(_aOps)){
CKademlia::debugMsg("*** Unknown integer search op=0x%02x (CreateSearchExpressionTree)", mmop);
return NULL;
}
// read tag name
CString strTagName;
uint16 lenTagName = bio.ReadUInt16();
bio.Read(strTagName.GetBuffer(lenTagName), lenTagName);
strTagName.ReleaseBuffer(lenTagName);
SSearchTerm* pSearchTerm = new SSearchTerm;
pSearchTerm->type = _aOps[mmop].eSearchTermOp;
pSearchTerm->tag = new Kademlia::CTagUInt32(strTagName, uValue);
if (lenTagName == 1)
TRACE(" Tag%02x%s%u", strTagName[0], _aOps[mmop].pszOp, uValue);
else
TRACE(" \"%s\"%s%u", strTagName, _aOps[mmop].pszOp, uValue);
return pSearchTerm;
}
else{
CKademlia::debugMsg("*** Unknown search op=0x%02x (CreateSearchExpressionTree)", op);
return NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -