📄 kademliaudplistener.cpp
字号:
}
else
{
//More then one size tag found
delete tag;
}
}
else if (!tag->m_name.Compare(TAG_SOURCEPORT))
{
if( entry->tcpport == 0 )
{
entry->tcpport = tag->GetInt();
entry->taglist.push_back(tag);
}
else
{
//More then one port tag found
delete tag;
}
}
else
{
//TODO: Filter tags
entry->taglist.push_back(tag);
}
}
tags--;
}
if (bDbgInfo && !strInfo.IsEmpty())
Debug(_T("%s\n"), strInfo);
}
catch(...)
{
delete entry;
throw;
}
if( entry->source == true )
{
if( indexed->AddSources(file, target, entry, load ) )
flag = true;
else
{
delete entry;
entry = NULL;
}
}
else
{
if( indexed->AddKeyword(file, target, entry, load) )
{
//This makes sure we send a publish response.. This also makes sure we index all the files for this keyword.
flag = true;
}
else
{
//We already indexed the maximum number of keywords.
//We do not index anymore but we still send a success..
//Reason: Because if a VERY busy node tells the publisher it failed,
//this busy node will spread to all the surrounding nodes causing popular
//keywords to be stored on MANY nodes..
//So, once we are full, we will periodically clean our list until we can
//begin storing again..
flag = true;
delete entry;
entry = NULL;
}
}
count--;
}
if( flag )
{
CSafeMemFile bio2(17);
bio2.WriteUInt128(&file);
bio2.WriteUInt8(load);
if (thePrefs.GetDebugClientKadUDPLevel() > 0)
DebugSend("KadPublishRes", ip, port);
sendPacket( &bio2, KADEMLIA_PUBLISH_RES, ip, port);
}
}
//KADEMLIA_PUBLISH_ACK
void CKademliaUDPListener::processPublishResponse (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port)
{
// Verify packet is expected size
if (lenPacket < 16){
CString strError;
strError.Format(_T("***NOTE: Received wrong size (%u) packet in %hs"), lenPacket, __FUNCTION__);
throw strError;
}
//Used Pointers
CRoutingZone *routingZone = CKademlia::getRoutingZone();
ASSERT(routingZone != NULL);
// Set contact to alive.
routingZone->setAlive(ip, port);
CSafeMemFile bio(packetData, lenPacket);
CUInt128 file;
bio.ReadUInt128(&file);
CSearchManager::processPublishResult(file);
}
//KADEMLIA_SRC_NOTES_REQ
void CKademliaUDPListener::processSearchNotesRequest (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port)
{
// Verify packet is expected size
if (lenPacket < 33){
CString strError;
strError.Format(_T("***NOTE: Received wrong size (%u) packet in %hs"), lenPacket, __FUNCTION__);
throw strError;
}
//Used Pointers
CIndexed *indexed = CKademlia::getIndexed();
ASSERT(indexed != NULL);
CSafeMemFile bio( packetData, lenPacket);
CUInt128 target;
bio.ReadUInt128(&target);
CUInt128 source;
bio.ReadUInt128(&source);
indexed->SendValidNoteResult(target, source, ip, port);
}
//KADEMLIA_SRC_NOTES_RES
void CKademliaUDPListener::processSearchNotesResponse (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port)
{
// Verify packet is expected size
if (lenPacket < 37){
CString strError;
strError.Format(_T("***NOTE: Received wrong size (%u) packet in %hs"), lenPacket, __FUNCTION__);
throw strError;
}
//Used Pointers
CRoutingZone *routingZone = CKademlia::getRoutingZone();
ASSERT(routingZone != NULL);
// Set contact to alive.
routingZone->setAlive(ip, port);
// What search does this relate to
CByteIO bio(packetData, lenPacket);
CUInt128 target;
bio.readUInt128(&target);
// How many results.. Not supported yet..
uint16 count = bio.readUInt16();
while( count > 0 )
{
// What is the answer
CUInt128 answer;
bio.readUInt128(&answer);
// 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 *tags = bio.readTagList(true/*bOptACP*/);
CSearchManager::processResult(target, ip, port, answer,tags);
count--;
}
}
//KADEMLIA_PUB_NOTES_REQ
void CKademliaUDPListener::processPublishNotesRequest (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port)
{
// Verify packet is expected size
if (lenPacket < 37){
CString strError;
strError.Format(_T("***NOTE: Received wrong size (%u) packet in %hs"), lenPacket, __FUNCTION__);
throw strError;
}
//Used Pointers
CIndexed *indexed = CKademlia::getIndexed();
ASSERT(indexed != NULL);
CPrefs *prefs = CKademlia::getPrefs();
ASSERT(prefs != NULL);
if( prefs->getFirewalled() )
//We are firewalled. We should not index this entry and give publisher a false report.
return;
CByteIO bio(packetData, lenPacket);
CUInt128 target;
bio.readUInt128(&target);
CUInt128 distance;
prefs->getKadID(&distance);
distance.xor(target);
if( thePrefs.FilterLANIPs() && distance.get32BitChunk(0) > SEARCHTOLERANCE)
return;
bool bDbgInfo = thePrefs.GetDebugClientKadUDPLevel() > 0;
CUInt128 source;
bio.readUInt128(&source);
Kademlia::CEntry* entry = new Kademlia::CEntry();
try
{
entry->ip = ip;
entry->udpport = port;
entry->keyID.setValue(target);
entry->sourceID.setValue(source);
uint32 tags = bio.readByte();
bio.readTagList( &(entry->taglist) );
entry->source = false;
}
catch(...)
{
delete entry;
throw;
}
if( entry == NULL )
{
throw CString(_T("CKademliaUDPListener::processPublishNotesRequest: entry == NULL"));
}
else if( entry->taglist.size() == 0 || entry->taglist.size() > 2)
{
delete entry;
throw CString(_T("CKademliaUDPListener::processPublishNotesRequest: entry->taglist.size() == 0 || entry->taglist.size() > 2"));
}
if( indexed->AddNotes(target, source, entry ) )
{
CSafeMemFile bio2(16);
bio2.WriteUInt128(&target);
if (thePrefs.GetDebugClientKadUDPLevel() > 0)
DebugSend("KadPublishNotesRes", ip, port);
sendPacket( &bio2, KADEMLIA_PUB_NOTES_RES, ip, port);
}
else
delete entry;
}
//KADEMLIA_PUB_NOTES_ACK
void CKademliaUDPListener::processPublishNotesResponse (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port)
{
// Verify packet is expected size
if (lenPacket < 16){
CString strError;
strError.Format(_T("***NOTE: Received wrong size (%u) packet in %hs"), lenPacket, __FUNCTION__);
throw strError;
}
//Used Pointers
CRoutingZone *routingZone = CKademlia::getRoutingZone();
ASSERT(routingZone != NULL);
// Set contact to alive.
routingZone->setAlive(ip, port);
}
//KADEMLIA_FIREWALLED_REQ
void CKademliaUDPListener::processFirewalledRequest (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port)
{
// Verify packet is expected size
if (lenPacket != 2){
CString strError;
strError.Format(_T("***NOTE: Received wrong size (%u) packet in %hs"), lenPacket, __FUNCTION__);
throw strError;
}
CSafeMemFile bio(packetData, lenPacket);
uint16 tcpport = bio.ReadUInt16();
CContact contact;
contact.setIPAddress(ip);
contact.setTCPPort(tcpport);
contact.setUDPPort(port);
theApp.clientlist->RequestTCP(&contact);
// Send response
CSafeMemFile bio2(4);
bio2.WriteUInt32(ip);
if (thePrefs.GetDebugClientKadUDPLevel() > 0)
DebugSend("KadFirewalledRes", ip, port);
sendPacket(&bio2, KADEMLIA_FIREWALLED_RES, ip, port);
}
//KADEMLIA_FIREWALLED_RES
void CKademliaUDPListener::processFirewalledResponse (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port)
{
// Verify packet is expected size
if (lenPacket != 4){
CString strError;
strError.Format(_T("***NOTE: Received wrong size (%u) packet in %hs"), lenPacket, __FUNCTION__);
throw strError;
}
//Used Pointers
CRoutingZone *routingZone = CKademlia::getRoutingZone();
ASSERT(routingZone != NULL);
// Set contact to alive.
routingZone->setAlive(ip, port);
CSafeMemFile bio(packetData, lenPacket);
uint32 firewalledIP = bio.ReadUInt32();
CPrefs *prefs = CKademlia::getPrefs();
ASSERT(prefs != NULL);
//Update con state only if something changes.
if( prefs->getIPAddress() != firewalledIP )
{
prefs->setIPAddress(firewalledIP);
theApp.emuledlg->ShowConnectionState();
}
prefs->incRecheckIP();
}
//KADEMLIA_FIREWALLED_ACK
void CKademliaUDPListener::processFirewalledResponse2 (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port)
{
// Verify packet is expected size
if (lenPacket != 0){
CString strError;
strError.Format(_T("***NOTE: Received wrong size (%u) packet in %hs"), lenPacket, __FUNCTION__);
throw strError;
}
//Used Pointers
CPrefs *prefs = CKademlia::getPrefs();
ASSERT(prefs != NULL);
CRoutingZone *routingZone = CKademlia::getRoutingZone();
ASSERT(routingZone != NULL);
// Set contact to alive.
routingZone->setAlive(ip, port);
prefs->incFirewalled();
}
//KADEMLIA_FINDBUDDY_REQ
void CKademliaUDPListener::processFindBuddyRequest (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port)
{
// Verify packet is expected size
if (lenPacket < 34){
CString strError;
strError.Format(_T("***NOTE: Received wrong size (%u) packet in %hs"), lenPacket, __FUNCTION__);
throw strError;
}
//Used Pointers
CPrefs *prefs = CKademlia::getPrefs();
ASSERT(prefs != NULL);
if( prefs->getFirewalled() )
//We are firewalled but somehow we still got this packet.. Don't send a response..
return;
CSafeMemFile bio(packetData, lenPacket);
CUInt128 BuddyID;
bio.ReadUInt128(&BuddyID);
CUInt128 userID;
bio.ReadUInt128(&userID);
uint16 tcpport = bio.ReadUInt16();
CContact contact;
contact.setIPAddress(ip);
contact.setTCPPort(tcpport);
contact.setUDPPort(port);
contact.setClientID(userID);
theApp.clientlist->IncomingBuddy(&contact, &BuddyID);
CSafeMemFile bio2(34);
bio2.WriteUInt128(&BuddyID);
bio2.WriteUInt128(&prefs->getClientHash());
bio2.WriteUInt16(thePrefs.GetPort());
if (thePrefs.GetDebugClientKadUDPLevel() > 0)
DebugSend("KadFindBuddyRes", ip, port);
sendPacket(&bio2, KADEMLIA_FINDBUDDY_RES, ip, port);
}
//KADEMLIA_FINDBUDDY_RES
void CKademliaUDPListener::processFindBuddyResponse (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port)
{
// Verify packet is expected size
if (lenPacket < 34){
CString strError;
strError.Format(_T("***NOTE: Received wrong size (%u) packet in %hs"), lenPacket, __FUNCTION__);
throw strError;
}
//Used Pointers
CPrefs *prefs = CKademlia::getPrefs();
ASSERT(prefs != NULL);
CSafeMemFile bio(packetData, lenPacket);
CUInt128 check;
bio.ReadUInt128(&check);
check.xor(CUInt128(true));
if( prefs->getKadID().compareTo(check))
return;
CUInt128 userID;
bio.ReadUInt128(&userID);
uint16 tcpport = bio.ReadUInt16();
CContact contact;
contact.setIPAddress(ip);
contact.setTCPPort(tcpport);
contact.setUDPPort(port);
contact.setClientID(userID);
theApp.clientlist->RequestBuddy(&contact);
}
//KADEMLIA_FINDSOURCE_REQ
void CKademliaUDPListener::processFindSourceRequest (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port)
{
// Verify packet is expected size
if (lenPacket < 34){
CString strError;
strError.Format(_T("***NOTE: Received wrong size (%u) packet in %hs"), lenPacket, __FUNCTION__);
throw strError;
}
//Used Pointers
CPrefs *prefs = CKademlia::getPrefs();
ASSERT(prefs != NULL);
CUpDownClient* buddy = theApp.clientlist->GetBuddy();
if( buddy != NULL )
{
CSafeMemFile bio(packetData, lenPacket);
CUInt128 check;
bio.ReadUInt128(&check);
CUInt128 bud(buddy->GetBuddyID());
CUInt128 file;
bio.ReadUInt128(&file);
uint16 tcp = bio.ReadUInt16();
CSafeMemFile bio2(lenPacket+6);
bio2.WriteUInt128(&check);
bio2.WriteUInt128(&file);
bio2.WriteUInt32(ip);
bio2.WriteUInt16(tcp);
Packet* packet = new Packet(&bio2, OP_EMULEPROT, OP_CALLBACK);
if( buddy->socket )
buddy->socket->SendPacket(packet);
else
ASSERT(0);
if (thePrefs.GetDebugClientKadUDPLevel() > 0)
DebugSend("KadCallback", ip, port);
}
}
void CKademliaUDPListener::sendPacket(const byte *data, uint32 lenData, uint32 destinationHost, uint16 destinationPort)
{
//This is temp.. The entire Kad code will be rewritten using CMemFile and send a Packet object directly.
Packet* packet = new Packet(OP_KADEMLIAHEADER);
packet->opcode = data[1];
packet->pBuffer = new char[lenData+8];
memcpy(packet->pBuffer, data+2, lenData-2);
packet->size = lenData-2;
if( lenData > 200 )
packet->PackPacket();
theStats.AddUpDataOverheadKad(packet->size);
theApp.clientudp->SendPacket(packet, ntohl(destinationHost), destinationPort);
}
void CKademliaUDPListener::sendPacket(const byte *data, uint32 lenData, byte opcode, uint32 destinationHost, uint16 destinationPort)
{
Packet* packet = new Packet(OP_KADEMLIAHEADER);
packet->opcode = opcode;
packet->pBuffer = new char[lenData];
memcpy(packet->pBuffer, data, lenData);
packet->size = lenData;
if( lenData > 200 )
packet->PackPacket();
theStats.AddUpDataOverheadKad(packet->size);
theApp.clientudp->SendPacket(packet, ntohl(destinationHost), destinationPort);
}
void CKademliaUDPListener::sendPacket(CSafeMemFile *data, byte opcode, uint32 destinationHost, uint16 destinationPort)
{
Packet* packet = new Packet(data, OP_KADEMLIAHEADER);
packet->opcode = opcode;
if( packet->size > 200 )
packet->PackPacket();
theStats.AddUpDataOverheadKad(packet->size);
theApp.clientudp->SendPacket(packet, ntohl(destinationHost), destinationPort);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -