kademliaudplistener.cpp

来自「wxWidgets写的电驴」· C++ 代码 · 共 1,226 行 · 第 1/3 页

CPP
1,226
字号
	//This makes sure we are not mistaken identify. Some client may have fresh installed and have a new hash.	CUInt128 check = bio.ReadUInt128();	if( CKademlia::getPrefs()->getKadID().compareTo(check)) {		return;	}	// Get required number closest to target	ContactMap results;	CKademlia::getRoutingZone()->getClosestTo(2, target, distance, (int)type, &results);	uint16 count = (uint16)results.size();	// Write response	// Max count is 32. size 817.. 	// 16 + 1 + 25(32)	CMemFile bio2( 817 );	bio2.WriteUInt128(target);	bio2.WriteUInt8((byte)count);	CContact *c;	ContactMap::const_iterator it;	for (it = results.begin(); it != results.end(); it++) {		c = it->second;		bio2.WriteUInt128(c->getClientID());		bio2.WriteUInt32(c->getIPAddress());		bio2.WriteUInt16(c->getUDPPort());		bio2.WriteUInt16(c->getTCPPort());		bio2.WriteUInt8(c->getType());	}	AddDebugLogLineM(false, logClientKadUDP, CFormat(wxT("KadRes %s Count=%u")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip), port) % count);	sendPacket(&bio2, KADEMLIA_RES, ip, port);}//KADEMLIA_RESvoid CKademliaUDPListener::processKademliaResponse (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port){	// Verify packet is expected size	if (lenPacket < 17){		throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket) + wxString::FromAscii(__FUNCTION__);		}	//Used Pointers	CRoutingZone *routingZone = CKademlia::getRoutingZone();	if(CKademlia::getPrefs()->getRecheckIP()) {		firewalledCheck(ip, port);		AddDebugLogLineM(false, logClientKadUDP, CFormat(wxT("KadHelloReq %s")) % Uint32_16toStringIP_Port(wxUINT32_SWAP_ALWAYS(ip), port));		sendMyDetails(KADEMLIA_HELLO_REQ, ip, port);	}	// What search does this relate to	CMemFile bio((byte*)packetData, lenPacket);	CUInt128 target = bio.ReadUInt128();	uint16 numContacts = bio.ReadUInt8();	// Verify packet is expected size	if (lenPacket != (uint32)(16+1 + (16+4+2+2+1)*numContacts)) {		throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket) + wxString::FromAscii(__FUNCTION__);	}	// Set contact to alive.	routingZone->setAlive(ip, port);		ContactList *results = new ContactList;	try {		for (uint16 i=0; i<numContacts; i++) {			CUInt128 id = bio.ReadUInt128();			uint32 contactIP = bio.ReadUInt32();			uint16 contactPort = bio.ReadUInt16();			uint16 tport = bio.ReadUInt16();			byte type = bio.ReadUInt8();			if(::IsGoodIPPort(wxUINT32_SWAP_ALWAYS(contactIP),contactPort)) {				routingZone->add(id, contactIP, contactPort, tport, type);				results->push_back(new CContact(id, contactIP, contactPort, tport, target));			}		}	} catch(...) {		delete results;		throw;	}	CSearchManager::processResponse(target, ip, port, results);}void CKademliaUDPListener::Free(SSearchTerm* pSearchTerms){	if (!pSearchTerms) {		return;	}	Free(pSearchTerms->left);	Free(pSearchTerms->right);	delete pSearchTerms;}SSearchTerm* CKademliaUDPListener::CreateSearchExpressionTree(CMemFile& 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){		AddDebugLogLineM(false, logClientKadUDP, wxT("***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){				wxASSERT(0);				delete pSearchTerm;				return NULL;			}			if ((pSearchTerm->right = CreateSearchExpressionTree(bio, iLevel)) == NULL){				wxASSERT(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){				wxASSERT(0);				delete pSearchTerm;				return NULL;			}			if ((pSearchTerm->right = CreateSearchExpressionTree(bio, iLevel)) == NULL){				wxASSERT(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){				wxASSERT(0);				delete pSearchTerm;				return NULL;			}			if ((pSearchTerm->right = CreateSearchExpressionTree(bio, iLevel)) == NULL){				wxASSERT(0);				Free(pSearchTerm->left);				delete pSearchTerm;				return NULL;			}			return pSearchTerm;		} else{			AddDebugLogLineM(false, logKadSearch, wxString::Format(wxT("*** Unknown boolean search operator 0x%02x (CreateSearchExpressionTree)"), boolop));			return NULL;		}	} else if (op == 0x01) { // String		CTagValueString str(bio.ReadString(true));		KadTagStrMakeLower(str); // make lowercase, the search code expects lower case strings!		//TRACE(" \"%ls\"", str);		SSearchTerm* pSearchTerm = new SSearchTerm;		pSearchTerm->type = SSearchTerm::String;		pSearchTerm->astr = new wxArrayString;		// pre-tokenize the string term		wxStringTokenizer token(str,InvKadKeywordChars,wxTOKEN_DEFAULT );		while (token.HasMoreTokens()) {			CTagValueString strTok(token.GetNextToken());			if (!strTok.IsEmpty()) {				pSearchTerm->astr->Add(strTok);			}		}		return pSearchTerm;	} else if (op == 0x02) { // Meta tag 		// read tag value		CTagValueString strValue(bio.ReadString(true));		KadTagStrMakeLower(strValue); // make lowercase, the search code expects lower case strings!		// read tag name		wxString strTagName =  bio.ReadString(true);		SSearchTerm* pSearchTerm = new SSearchTerm;		pSearchTerm->type = SSearchTerm::MetaTag;		pSearchTerm->tag = new Kademlia::CTagStr(strTagName, strValue);		return pSearchTerm;	}	else if (op == 0x03) { // Min/Max		static const struct {			SSearchTerm::ESearchTermType eSearchTermOp;			wxString pszOp;		} _aOps[] =		{			{ SSearchTerm::OpEqual,			wxT("=")		}, // mmop=0x00			{ SSearchTerm::OpGreaterEqual,	wxT(">=")	}, // mmop=0x01			{ SSearchTerm::OpLessEqual,		wxT("<=")	}, // mmop=0x02			{ SSearchTerm::OpGreater,		wxT(">")		}, // mmop=0x03			{ SSearchTerm::OpLess,			wxT("<")		}, // mmop=0x04			{ SSearchTerm::OpNotEqual,		wxT("!=")	}  // mmop=0x05		};		// read tag value		uint32 uValue = bio.ReadUInt32();		// read integer operator		uint8 mmop = bio.ReadUInt8();		if (mmop >= ARRSIZE(_aOps)){			AddDebugLogLineM(false, logClientKadUDP, wxString::Format(wxT("*** Unknown integer search op=0x%02x (CreateSearchExpressionTree)"), mmop));			return NULL;		}		// read tag name		wxString strTagName = bio.ReadString(false);		SSearchTerm* pSearchTerm = new SSearchTerm;		pSearchTerm->type = _aOps[mmop].eSearchTermOp;		pSearchTerm->tag = new Kademlia::CTagUInt32(strTagName, uValue);		return pSearchTerm;	} else{		AddDebugLogLineM(false, logClientKadUDP, wxString::Format(wxT("*** Unknown search op=0x%02x (CreateSearchExpressionTree)"), op));		return NULL;	}}//KADEMLIA_SEARCH_REQvoid CKademliaUDPListener::processSearchRequest (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port){	// Verify packet is expected size	if (lenPacket < 17){		throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket) + wxString::FromAscii(__FUNCTION__);			}	CMemFile bio((byte*)packetData, lenPacket);	CUInt128 target = bio.ReadUInt128();	uint8 restrictive = bio.ReadUInt8();#ifdef _DEBUG	//DWORD dwNow = GetTickCount();#endif	if(lenPacket == 17 ) {		if(restrictive) {			//Source request			CKademlia::getIndexed()->SendValidSourceResult(target, ip, port);			//DEBUG_ONLY( Debug("SendValidSourceResult: Time=%.2f sec\n", (GetTickCount() - dwNow) / 1000.0) );		} else {			//Single keyword request			CKademlia::getIndexed()->SendValidKeywordResult(target, NULL, ip, port );			//DEBUG_ONLY( Debug("SendValidKeywordResult (Single): Time=%.2f sec\n", (GetTickCount() - dwNow) / 1000.0) );		}	} else if(lenPacket > 17) {		SSearchTerm* pSearchTerms = NULL;		if (restrictive) {			try {				pSearchTerms = CreateSearchExpressionTree(bio, 0);				//TRACE("\n");			} catch(...) {				Free(pSearchTerms);				throw;			}		}		//Keyword request with added options.		CKademlia::getIndexed()->SendValidKeywordResult(target, pSearchTerms, ip, port); 		Free(pSearchTerms);		//DEBUG_ONLY( Debug("SendValidKeywordResult: Time=%.2f sec\n", (GetTickCount() - dwNow) / 1000.0) );	}}//KADEMLIA_SEARCH_RESvoid CKademliaUDPListener::processSearchResponse (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port){	// Verify packet is expected size	if (lenPacket < 37) {		throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket) + wxString::FromAscii(__FUNCTION__);	}	// Set contact to alive.	CKademlia::getRoutingZone()->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 = new TagList;		try {			bio.readTagList(tags, true/*bOptACP*/);		} catch(...){			DebugClientOutput(wxT("CKademliaUDPListener::processSearchResponse"),ip,port);			deleteTagListEntries(tags);			delete tags;			tags = NULL;			throw;		}		CSearchManager::processResult(target, ip, port, answer, tags);		count--;	}}//KADEMLIA_PUBLISH_REQvoid CKademliaUDPListener::processPublishRequest (const byte *packetData, uint32 lenPacket, uint32 ip, uint16 port){	//There are different types of publishing..	//Keyword and File are Stored..	// Verify packet is expected size	if (lenPacket < 37) {		throw wxString::Format(wxT("***NOTE: Received wrong size (%u) packet in "), lenPacket) + wxString::FromAscii(__FUNCTION__);	}	//Used Pointers	CIndexed *indexed = CKademlia::getIndexed();	if( CKademlia::getPrefs()->getFirewalled() ) {		//We are firewalled. We should not index this entry and give publisher a false report.		return;	}	CByteIO bio(packetData, lenPacket);	CUInt128 file;	bio.readUInt128(&file);	CUInt128 distance(CKademlia::getPrefs()->getKadID());	distance.XOR(file);	if( thePrefs::FilterLanIPs() && distance.get32BitChunk(0) > SEARCHTOLERANCE) {		return;	}	wxString strInfo;	uint16 count = bio.readUInt16();	bool flag = false;	uint8 load = 0;	while( count > 0 ) {		strInfo.Clear();		CUInt128 target;		bio.readUInt128(&target);		Kademlia::CEntry* entry = new Kademlia::CEntry();		try {			entry->ip = ip;			entry->udpport = port;			entry->keyID.setValue(file);			entry->sourceID.setValue(target);			uint32 tags = bio.readByte();			while(tags > 0) {				CTag* tag = bio.readTag();				if(tag) {					if (!tag->m_name.Cmp(wxT(TAG_SOURCETYPE)) && tag->m_type == 9) {						if( entry->source == false ) {							entry->taglist.push_back(new CTagUInt32(TAG_SOURCEIP, entry->ip));							entry->taglist.push_back(new CTagUInt16(TAG_SOURCEUPORT, entry->udpport));						} else {							//More than one sourcetype tag found.							delete tag;						}						entry->source = true;					}										if (!tag->m_name.Cmp(wxT(TAG_FILENAME))) {						if ( entry->fileName.IsEmpty() ) {							entry->fileName = tag->GetStr();							KadTagStrMakeLower(entry->fileName); // make lowercase, the search code expects lower case strings!														strInfo += CFormat(wxT("  Name=\"%s\"")) % entry->fileName;							// NOTE: always add the 'name' tag, even if it's stored separately in 'fileName'. the tag is still needed for answering search request							entry->taglist.push_back(tag);						} else {							//More then one Name tag found.							delete tag;						}					} else if (!tag->m_name.Cmp(wxT(TAG_FILESIZE))) {						if( entry->size == 0 ) {							entry->size = tag->GetInt();							strInfo += wxString::Format(wxT("  Size=%u"), entry->size);							// NOTE: always add the 'size' tag, even if it's stored separately in 'size'. the tag is still needed for answering search request							entry->taglist.push_back(tag);						} else {							//More then one size tag found							delete tag;						}					} else if (!tag->m_name.Cmp(wxT(TAG_SOURCEPORT))) {						if( entry->tcpport == 0 ) {							entry->tcpport = tag->GetInt();							entry->taglist.push_back(tag);						} else {							//More then one port tag found							delete tag;						}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?