📄 kademliaudplistener.cpp
字号:
//KADEMLIA_HELLO_REQ
void CKademliaUDPListener::processHelloRequest (const byte *packetData, const uint32 lenPacket, const sockaddr_in *senderAddress)
{
try
{
if (lenPacket != 25){
ASSERT(0);
return;
}
//Used Pointers
CPrefs *prefs = CKademlia::getPrefs();
ASSERT(prefs != NULL);
// Add the sender to the list of contacts
addContact(packetData, lenPacket, ntohl(senderAddress->sin_addr.s_addr), ntohs(senderAddress->sin_port));
// Send response
// CKademlia::debugMsg("Sent UDP OpCode KADEMLIA_HELLO_RES (%u)", ntohl(senderAddress->sin_addr.s_addr));
sendMyDetails(KADEMLIA_HELLO_RES,ntohl(senderAddress->sin_addr.s_addr), ntohs(senderAddress->sin_port));
if(prefs->getRecheckIP())
{
// Check if firewalled
firewalledCheck(ntohl(senderAddress->sin_addr.s_addr), ntohs(senderAddress->sin_port));
}
} catch (...) {TRACE("Exception in Kademlia Hello Requests\n");}
}
//KADEMLIA_HELLO_RES
void CKademliaUDPListener::processHelloResponse (const byte *packetData, const uint32 lenPacket, const sockaddr_in *senderAddress)
{
try
{
if (lenPacket != 25){
ASSERT(0);
return;
}
//Used Pointers
CRoutingZone *routingZone = CKademlia::getRoutingZone();
ASSERT(routingZone != NULL);
CPrefs *prefs = CKademlia::getPrefs();
ASSERT(prefs != NULL);
// Add or Update contact.
addContact(packetData, lenPacket, ntohl(senderAddress->sin_addr.s_addr), ntohs(senderAddress->sin_port));
// Set contact to alive.
routingZone->setAlive(ntohl(senderAddress->sin_addr.s_addr), ntohs(senderAddress->sin_port));
} catch (...) {TRACE("Exception in Kademlia Hello Response\n");}
}
//KADEMLIA_REQ
void CKademliaUDPListener::processKademliaRequest (const byte *packetData, const uint32 lenPacket, const sockaddr_in *senderAddress)
{
try
{
// Verify packet is expected size
if (lenPacket != 33){
ASSERT(0);
return;
}
//Used Pointers
CPrefs *prefs = CKademlia::getPrefs();
ASSERT(prefs != NULL);
CRoutingZone *routingZone = CKademlia::getRoutingZone();
ASSERT(routingZone != NULL);
if(prefs->getRecheckIP())
{
firewalledCheck(ntohl(senderAddress->sin_addr.s_addr), ntohs(senderAddress->sin_port));
sendMyDetails(KADEMLIA_HELLO_REQ, ntohl(senderAddress->sin_addr.s_addr), ntohs(senderAddress->sin_port));
}
// Get target and type
CByteIO bio(packetData, lenPacket);
byte type = bio.readByte();
CUInt128 target;
bio.readUInt128(&target);
CUInt128 check;
bio.readUInt128(&check);
if( prefs->getClientID().compareTo(check))
return;
// Get required number closest to target
ContactMap results;
CUInt128 distance(prefs->getClientID());
distance.xor(target);
routingZone->getClosestTo(0, distance, (int)type, &results);
uint16 count = (uint16)results.size();
// Write response
uint32 lenResponse = 1+1+16+1 + (16+4+2+2+1)*count;
byte response[1024];
ASSERT(lenResponse <= sizeof(response));
CByteIO bio2(response, lenResponse);
bio2.writeByte(OP_KADEMLIAHEADER);
bio2.writeByte(KADEMLIA_RES);
bio2.writeUInt128(target);
bio2.writeByte((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.writeByte(c->getType());
}
// CKademlia::debugMsg("Sent UDP OpCode KADEMLIA_RES (%u)", ntohl(senderAddress->sin_addr.s_addr));
sendPacket(response, lenResponse, ntohl(senderAddress->sin_addr.s_addr), ntohs(senderAddress->sin_port));
} catch (...) {TRACE("Exception in Kademlia Request\n");}
}
//KADEMLIA_RES
void CKademliaUDPListener::processKademliaResponse (const byte *packetData, const uint32 lenPacket, const sockaddr_in *senderAddress)
{
try
{
// Verify packet is expected size
if (lenPacket < 17){
ASSERT(0);
return;
}
//Used Pointers
CPrefs *prefs = CKademlia::getPrefs();
ASSERT(prefs != NULL);
CRoutingZone *routingZone = CKademlia::getRoutingZone();
ASSERT(routingZone != NULL);
if(prefs->getRecheckIP())
{
firewalledCheck(ntohl(senderAddress->sin_addr.s_addr), ntohs(senderAddress->sin_port));
sendMyDetails(KADEMLIA_HELLO_REQ, ntohl(senderAddress->sin_addr.s_addr), ntohs(senderAddress->sin_port));
}
// What search does this relate to
CByteIO bio(packetData, lenPacket);
CUInt128 target;
bio.readUInt128(&target);
uint16 numContacts = bio.readByte();
// Verify packet is expected size
if (lenPacket != 16+1 + (16+4+2+2+1)*numContacts){
ASSERT(0);
return;
}
// Set contact to alive.
routingZone->setAlive(ntohl(senderAddress->sin_addr.s_addr), ntohs(senderAddress->sin_port));
CUInt128 id;
ContactList *results = new ContactList;
for (uint16 i=0; i<numContacts; i++)
{
bio.readUInt128(&id);
uint32 ip = bio.readUInt32(); // Not LE
uint16 port = bio.readUInt16();
uint16 tport = bio.readUInt16();
byte type = bio.readByte();
if(::IsGoodIPPort(ntohl(ip),port))
{
routingZone->add(id, ip, port, tport, type);
results->push_back(new CContact(id, ip, port, tport, type, target));
}
}
CSearchManager::processResponse(target,
ntohl(senderAddress->sin_addr.s_addr), ntohs(senderAddress->sin_port),
results);
} catch (...) {TRACE("Exception in Kademlia Response\n");}
}
void Free(SSearchTerm* pSearchTerms)
{
if (pSearchTerms->left)
Free(pSearchTerms->left);
if (pSearchTerms->right)
Free(pSearchTerms->right);
delete pSearchTerms;
}
SSearchTerm* CreateSearchExpressionTree(CByteIO& bio, int iLevel)
{
// the max. depth has to match our own limit for creating the search expression
// (see also 'ParsedSearchExpression' and 'GetSearchPacket')
if (iLevel >= 16){
TRACE("*** Search expression tree exceeds depth limit!\n");
return NULL;
}
iLevel++;
uint8 op = bio.readByte();
if (op == 0x00){
uint8 boolop = bio.readByte();
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{
TRACE("*** Unknown boolean search operator 0x%02x\n", boolop);
return NULL;
}
}
else if (op == 0x01){ // String
SSearchTerm* pSearchTerm = new SSearchTerm;
pSearchTerm->type = SSearchTerm::String;
uint16 len = bio.readUInt16();
pSearchTerm->str = new CString;
bio.readArray(pSearchTerm->str->GetBuffer(len), len);
pSearchTerm->str->ReleaseBuffer(len);
TRACE(" \"%s\"", *(pSearchTerm->str));
return pSearchTerm;
}
else if (op == 0x02){ // Meta tag
SSearchTerm* pSearchTerm = new SSearchTerm;
pSearchTerm->type = SSearchTerm::MetaTag;
// read tag value
CString strValue;
uint16 lenValue = bio.readUInt16();
bio.readArray(strValue.GetBuffer(lenValue), lenValue);
strValue.ReleaseBuffer(lenValue);
// read tag name
CString strTagName;
uint16 lenTagName = bio.readUInt16();
bio.readArray(strTagName.GetBuffer(lenTagName), lenTagName);
strTagName.ReleaseBuffer(lenTagName);
pSearchTerm->tag = new Kademlia::CTagStr(strTagName, strValue);
if (lenTagName == 1)
TRACE(" Tag%02x=\"%s\"", strTagName[0], strValue);
else
TRACE(" Tag\"%s\"=\"%s\"", strTagName, strValue);
return pSearchTerm;
}
else if (op == 0x03){ // Min/Max
SSearchTerm* pSearchTerm = new SSearchTerm;
// read tag value
uint32 uValue = bio.readUInt32();
// read min/max operator
uint8 mmop = bio.readByte();
pSearchTerm->type = (mmop == 0x01) ? SSearchTerm::Min : SSearchTerm::Max;
// read tag name
CString strTagName;
uint16 lenTagName = bio.readUInt16();
bio.readArray(strTagName.GetBuffer(lenTagName), lenTagName);
strTagName.ReleaseBuffer(lenTagName);
pSearchTerm->tag = new Kademlia::CTagUInt32(strTagName, uValue);
if (lenTagName == 1)
TRACE(" %s(Tag%02x)=%u", pSearchTerm->type == SSearchTerm::Min ? "Min" : "Max", strTagName[0], uValue);
else
TRACE(" %s(Tag\"%s\")=%u", pSearchTerm->type == SSearchTerm::Min ? "Min" : "Max", strTagName, uValue);
return pSearchTerm;
}
else{
TRACE("*** Unknown search op=0x%02x\n", op);
return NULL;
}
}
//KADEMLIA_SEARCH_REQ
void CKademliaUDPListener::processSearchRequest (const byte *packetData, const uint32 lenPacket, const sockaddr_in *senderAddress)
{
try
{
if (lenPacket < 17){
ASSERT(0);
return;
}
//Used Pointers
CIndexed *indexed = CKademlia::getIndexed();
ASSERT(indexed != NULL);
CByteIO bio(packetData, lenPacket);
CUInt128 target;
bio.readUInt128(&target);
uint8 restrictive = bio.readByte();
if(lenPacket == 17 ){
if(restrictive)
{
//Source request
indexed->SendValidResult(target, NULL, senderAddress, true );
}
else
{
//Single keyword request
indexed->SendValidResult(target, NULL, senderAddress, false );
}
}
else if(lenPacket > 17){
SSearchTerm* pSearchTerms = NULL;
if (restrictive){
pSearchTerms = CreateSearchExpressionTree(bio, 0);
}
//Keyword request with added options.
indexed->SendValidResult(target, pSearchTerms, senderAddress, false );
Free(pSearchTerms);
}
} catch (...) {TRACE("Exception in Kademlia Search Request\n");}
}
//KADEMLIA_SEARCH_RES
void CKademliaUDPListener::processSearchResponse (const byte *packetData, const uint32 lenPacket, const sockaddr_in *senderAddress)
{
try
{
// Verify packet is expected size
if (lenPacket < 37){
ASSERT(0);
return;
}
//Used Pointers
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -