Example #1
0
/// Byte-swap the summary data, in case it was saved by a system
/// on a different platform
void BlockFile::FixSummary(void *data)
{
   if (mSummaryInfo.format != floatSample ||
       mSummaryInfo.fields != 3)
      return;

   float *summary64K = (float *)((char *)data + mSummaryInfo.offset64K);
   float *summary256 = (float *)((char *)data + mSummaryInfo.offset256);

   float min, max;
   int bad;
   int i;

   ComputeMinMax256(summary256, &min, &max, &bad);

   if (min != summary64K[0] || max != summary64K[1] || bad > 0) {
      unsigned int *buffer = (unsigned int *)data;
      int len = mSummaryInfo.totalSummaryBytes / 4;

      for(i=0; i<len; i++)
         buffer[i] = wxUINT32_SWAP_ALWAYS(buffer[i]);

      ComputeMinMax256(summary256, &min, &max, &bad);
      if (min == summary64K[0] && max == summary64K[1] && bad == 0) {
         // The byte-swapping worked!
         return;
      }

      // Hmmm, no better, we should swap back

      for(i=0; i<len; i++)
         buffer[i] = wxUINT32_SWAP_ALWAYS(buffer[i]);
   }   
}
Example #2
0
void CECTag::InitInt(uint64 data)
{
	if (data <= 0xFF) {
		m_dataType = EC_TAGTYPE_UINT8;
		m_dataLen = 1;
	} else if (data <= 0xFFFF) {
		m_dataType = EC_TAGTYPE_UINT16;
		m_dataLen = 2;
	} else if (data <= 0xFFFFFFFF) {
		m_dataType = EC_TAGTYPE_UINT32;
		m_dataLen = 4;
	} else {
		m_dataType = EC_TAGTYPE_UINT64;
		m_dataLen = 8;
	}

	NewData();

	switch (m_dataType) {
		case EC_TAGTYPE_UINT8:
			PokeUInt8( m_tagData, (uint8) data );
			break;
		case EC_TAGTYPE_UINT16:
			PokeUInt16( m_tagData, wxUINT16_SWAP_ALWAYS((uint16) data ));
			break;
		case EC_TAGTYPE_UINT32:
			PokeUInt32( m_tagData, wxUINT32_SWAP_ALWAYS((uint32) data ));
			break;
		case EC_TAGTYPE_UINT64:
			PokeUInt64( m_tagData, wxUINT64_SWAP_ALWAYS(data) );
			break;
	}
}
Example #3
0
bool CClientList::IncomingBuddy(Kademlia::CContact* contact, Kademlia::CUInt128* buddyID)
{
	uint32_t nContactIP = wxUINT32_SWAP_ALWAYS(contact->GetIPAddress());
	//If aMule already knows this client, abort this.. It could cause conflicts.
	//Although the odds of this happening is very small, it could still happen.
	if (FindClientByIP(nContactIP, contact->GetTCPPort())) {
		return false;
	} else if (IsKadFirewallCheckIP(nContactIP)) { // doing a kad firewall check with this IP, abort
		AddDebugLogLineN(logKadMain, wxT("Kad TCP firewallcheck / Buddy request collision for IP ") + Uint32toStringIP(nContactIP));
		return false;
	}

	if (theApp->GetPublicIP() == nContactIP && thePrefs::GetPort() == contact->GetTCPPort()) {
		return false; // don't connect ourself
	}

	//Add client to the lists to be processed.
	CUpDownClient* pNewClient = new CUpDownClient(contact->GetTCPPort(), contact->GetIPAddress(), 0, 0, NULL, false, true );
	pNewClient->SetKadPort(contact->GetUDPPort());
	pNewClient->SetKadState(KS_INCOMING_BUDDY);
	byte ID[16];
	contact->GetClientID().ToByteArray(ID);
	pNewClient->SetUserHash(CMD4Hash(ID));
	buddyID->ToByteArray(ID);
	pNewClient->SetBuddyID(ID);
	AddToKadList(pNewClient);
	AddClient(pNewClient);
	return true;
}
Example #4
0
void CClientList::RequestBuddy(Kademlia::CContact* contact, uint8_t connectOptions)
{
	uint32_t nContactIP = wxUINT32_SWAP_ALWAYS(contact->GetIPAddress());
	// Don't connect to ourself
	if (theApp->GetPublicIP() == nContactIP && thePrefs::GetPort() == contact->GetTCPPort()) {
		return;
	}

	CUpDownClient* pNewClient = FindClientByIP(nContactIP, contact->GetTCPPort());
	if (!pNewClient) {
		pNewClient = new CUpDownClient(contact->GetTCPPort(), contact->GetIPAddress(), 0, 0, NULL, false, true );
	} else if (pNewClient->GetKadState() != KS_NONE) {
		return; // already busy with this client in some way (probably fw stuff), don't mess with it
	} else if (IsKadFirewallCheckIP(nContactIP)) { // doing a kad firewall check with this IP, abort
		AddDebugLogLineN(logKadMain, wxT("Kad TCP firewallcheck / Buddy request collision for IP ") + Uint32toStringIP(nContactIP));
		return;
	}

	//Add client to the lists to be processed.
	pNewClient->SetKadPort(contact->GetUDPPort());
	pNewClient->SetKadState(KS_QUEUED_BUDDY);
	uint8_t ID[16];
	contact->GetClientID().ToByteArray(ID);
	pNewClient->SetUserHash(CMD4Hash(ID));
	pNewClient->SetConnectOptions(connectOptions, true, false);
	AddToKadList(pNewClient);
	//This method checks if this is a dup already.
	AddClient(pNewClient);
}
Example #5
0
bool CClientList::RequestTCP(Kademlia::CContact* contact, uint8_t connectOptions)
{
	uint32_t nContactIP = wxUINT32_SWAP_ALWAYS(contact->GetIPAddress());
	// don't connect ourself
	if (theApp->GetPublicIP() == nContactIP && thePrefs::GetPort() == contact->GetTCPPort()) {
		return false;
	}

	CUpDownClient* pNewClient = FindClientByIP(nContactIP, contact->GetTCPPort());

	if (!pNewClient) {
		//#warning Do we actually have to check friendstate here?
		pNewClient = new CUpDownClient(contact->GetTCPPort(), contact->GetIPAddress(), 0, 0, NULL, false, true);
	} else if (pNewClient->GetKadState() != KS_NONE) {
		return false; // already busy with this client in some way (probably buddy stuff), don't mess with it
	}

	//Add client to the lists to be processed.
	pNewClient->SetKadPort(contact->GetUDPPort());
	pNewClient->SetKadState(KS_QUEUED_FWCHECK);
	if (contact->GetClientID() != 0) {
		uint8_t ID[16];
		contact->GetClientID().ToByteArray(ID);
		pNewClient->SetUserHash(CMD4Hash(ID));
		pNewClient->SetConnectOptions(connectOptions, true, false);
	}
	AddToKadList(pNewClient); // This was a direct adding, but I like to check duplicates
	//This method checks if this is a dup already.
	AddClient(pNewClient);
	return true;
}
Example #6
0
void CDownloadQueue::CheckAndAddKnownSource(CPartFile* sender,CUpDownClient* source)
{
	// Kad reviewed
	
	if (sender->IsStopped()) {
		return;
	}

	// Filter sources which are known to be dead/useless
	if ( sender->IsDeadSource(source) ) {
		return;
	}

	// "Filter LAN IPs" -- this may be needed here in case we are connected to the internet and are also connected
	// to a LAN and some client from within the LAN connected to us. Though this situation may be supported in future
	// by adding that client to the source list and filtering that client's LAN IP when sending sources to
	// a client within the internet.
	//
	// "IPfilter" is not needed here, because that "known" client was already IPfiltered when receiving OP_HELLO.
	if (!source->HasLowID()) {
		uint32 nClientIP = wxUINT32_SWAP_ALWAYS(source->GetUserIDHybrid());
		if (!IsGoodIP(nClientIP, thePrefs::FilterLanIPs())) { // check for 0-IP, localhost and LAN addresses
			AddDebugLogLineN(logIPFilter, wxT("Ignored already known source with IP=%s") + Uint32toStringIP(nClientIP));
			return;
		}
	}	
	
	// Filter sources which are incompatible with our encryption setting (one requires it, and the other one doesn't supports it)
	if ( (source->RequiresCryptLayer() && (!thePrefs::IsClientCryptLayerSupported() || !source->HasValidHash())) || (thePrefs::IsClientCryptLayerRequired() && (!source->SupportsCryptLayer() || !source->HasValidHash())))
	{
		source->Safe_Delete();
		return;
	}		
	
	CPartFile* file = source->GetRequestFile();
	
	// Check if the file is already queued for something else
	if ( file ) {
		if ( file != sender ) {
			if ( source->AddRequestForAnotherFile( sender ) ) {
				Notify_SourceCtrlAddSource( sender, CCLIENTREF(source, wxT("CDownloadQueue::CheckAndAddKnownSource Notify_SourceCtrlAddSource 1")), A4AF_SOURCE );
			}
		}
	} else {
		source->SetRequestFile( sender );

		if ( source->GetFileRating() || !source->GetFileComment().IsEmpty() ) {
			sender->UpdateFileRatingCommentAvail();
		}

		source->SetSourceFrom(SF_PASSIVE);
		sender->AddSource( source );
		Notify_SourceCtrlAddSource( sender, CCLIENTREF(source, wxT("CDownloadQueue::CheckAndAddKnownSource Notify_SourceCtrlAddSource 2")), UNAVAILABLE_SOURCE);
	}
}
Example #7
0
bool CClientList::DoRequestFirewallCheckUDP(const Kademlia::CContact& contact)
{
	// first make sure we don't know this IP already from somewhere
	if (IsIPAlreadyKnown(wxUINT32_SWAP_ALWAYS(contact.GetIPAddress()))) {
		return false;
	}
	// fine, just create the client object, set the state and wait
	// TODO: We don't know the client's userhash, this means we cannot build an obfuscated connection, which
	// again mean that the whole check won't work on "Require Obfuscation" setting, which is not a huge problem,
	// but certainly not nice. Only somewhat acceptable way to solve this is to use the KadID instead.
	CUpDownClient* pNewClient = new CUpDownClient(contact.GetTCPPort(), contact.GetIPAddress(), 0, 0, NULL, false, true);
	pNewClient->SetKadState(KS_QUEUED_FWCHECK_UDP);
	AddDebugLogLineN(logClient, wxT("Selected client for UDP Firewallcheck: ") + KadIPToString(contact.GetIPAddress()));
	AddToKadList(pNewClient);
	AddClient(pNewClient);
	wxASSERT(!pNewClient->SupportsDirectUDPCallback());
	return true;
}
Example #8
0
void CDownloadQueue::KademliaSearchFile(uint32_t searchID, const Kademlia::CUInt128* pcontactID, const Kademlia::CUInt128* pbuddyID, uint8_t type, uint32_t ip, uint16_t tcp, uint16_t udp, uint32_t buddyip, uint16_t buddyport, uint8_t byCryptOptions)
{
	AddDebugLogLineN(logKadSearch, CFormat(wxT("Search result sources (type %i)")) % type);

	//Safety measure to make sure we are looking for these sources
	CPartFile* temp = GetFileByKadFileSearchID(searchID);
	if( !temp ) {
		AddDebugLogLineN(logKadSearch, wxT("This is not the file we're looking for..."));
		return;
	}

	//Do we need more sources?
	if(!(!temp->IsStopped() && thePrefs::GetMaxSourcePerFile() > temp->GetSourceCount())) {
		AddDebugLogLineN(logKadSearch, wxT("No more sources needed for this file"));
		return;
	}

	uint32_t ED2KID = wxUINT32_SWAP_ALWAYS(ip);

	if (theApp->ipfilter->IsFiltered(ED2KID)) {
		AddDebugLogLineN(logKadSearch, wxT("Source ip got filtered"));
		AddDebugLogLineN(logIPFilter, CFormat(wxT("IPfiltered source IP=%s received from Kademlia")) % Uint32toStringIP(ED2KID));
		return;
	}

	if( (ip == Kademlia::CKademlia::GetIPAddress() || ED2KID == theApp->GetED2KID()) && tcp == thePrefs::GetPort()) {
		AddDebugLogLineN(logKadSearch, wxT("Trying to add myself as source, ignore"));
		return;
	}

	CUpDownClient* ctemp = NULL; 
	switch (type) {
		case 4:
		case 1: {
			// NonFirewalled users
			if(!tcp) {
				AddDebugLogLineN(logKadSearch, CFormat(wxT("Ignored source (IP=%s) received from Kademlia, no tcp port received")) % Uint32toStringIP(ip));
				return;
			}
			if (!IsGoodIP(ED2KID,thePrefs::FilterLanIPs())) {
				AddDebugLogLineN(logKadSearch, CFormat(wxT("%s got filtered")) % Uint32toStringIP(ED2KID));
				AddDebugLogLineN(logIPFilter, CFormat(wxT("Ignored source (IP=%s) received from Kademlia, filtered")) % Uint32toStringIP(ED2KID));
				return;
			}
			ctemp = new CUpDownClient(tcp, ip, 0, 0, temp, false, true);
			ctemp->SetSourceFrom(SF_KADEMLIA);
			// not actually sent or needed for HighID sources
			//ctemp->SetServerIP(serverip);
			//ctemp->SetServerPort(serverport);
			ctemp->SetKadPort(udp);
			byte cID[16];
			pcontactID->ToByteArray(cID);
			ctemp->SetUserHash(CMD4Hash(cID));
			break;
		}
		case 2: {
			// Don't use this type... Some clients will process it wrong..
			break;
		}
		case 5:
		case 3: {
			// This will be a firewalled client connected to Kad only.
			// We set the clientID to 1 as a Kad user only has 1 buddy.
			ctemp = new CUpDownClient(tcp, 1, 0, 0, temp, false, true);
			// The only reason we set the real IP is for when we get a callback
			// from this firewalled source, the compare method will match them.
			ctemp->SetSourceFrom(SF_KADEMLIA);
			ctemp->SetKadPort(udp);
			byte cID[16];
			pcontactID->ToByteArray(cID);
			ctemp->SetUserHash(CMD4Hash(cID));
			pbuddyID->ToByteArray(cID);
			ctemp->SetBuddyID(cID);
			ctemp->SetBuddyIP(buddyip);
			ctemp->SetBuddyPort(buddyport);
			break;
		}
		case 6: {
			// firewalled source which supports direct UDP callback
			// if we are firewalled ourself, the source is useless to us
			if (theApp->IsFirewalled()) {
				break;
			}

			if ((byCryptOptions & 0x08) == 0){
				AddDebugLogLineN(logKadSearch, CFormat(wxT("Received Kad source type 6 (direct callback) which has the direct callback flag not set (%s)")) % Uint32toStringIP(ED2KID));
				break;
			}

			ctemp = new CUpDownClient(tcp, 1, 0, 0, temp, false, true);
			ctemp->SetSourceFrom(SF_KADEMLIA);
			ctemp->SetKadPort(udp);
			ctemp->SetIP(ED2KID); // need to set the IP address, which cannot be used for TCP but for UDP
			byte cID[16];
			pcontactID->ToByteArray(cID);
			ctemp->SetUserHash(CMD4Hash(cID));
		}
	}

	if (ctemp) {
		// add encryption settings
		ctemp->SetConnectOptions(byCryptOptions);

		AddDebugLogLineN(logKadSearch, CFormat(wxT("Happily adding a source (%s) type %d")) % Uint32_16toStringIP_Port(ED2KID, ctemp->GetUserPort()) % type);
		CheckAndAddSource(temp, ctemp);
	}
}
Example #9
0
void CClientList::Process()
{
	const uint32 cur_tick = ::GetTickCount();

	if (m_dwLastBannCleanUp + BAN_CLEANUP_TIME < cur_tick) {
		m_dwLastBannCleanUp = cur_tick;

		ClientMap::iterator it = m_bannedList.begin();
		while ( it != m_bannedList.end() ) {
			if ( it->second + CLIENTBANTIME < cur_tick ) {
				ClientMap::iterator tmp = it++;

				m_bannedList.erase( tmp );
				theStats::RemoveBannedClient();
			} else {
				++it;
			}
		}
	}


	if ( m_dwLastTrackedCleanUp + TRACKED_CLEANUP_TIME < cur_tick ) {
		m_dwLastTrackedCleanUp = cur_tick;

		std::map<uint32, CDeletedClient*>::iterator it = m_trackedClientsList.begin();
		while ( it != m_trackedClientsList.end() ) {
			std::map<uint32, CDeletedClient*>::iterator cur_src = it++;

			if ( cur_src->second->m_dwInserted + KEEPTRACK_TIME < cur_tick ) {
				delete cur_src->second;
				m_trackedClientsList.erase( cur_src );
			}
		}
	}

	//We need to try to connect to the clients in m_KadList
	//If connected, remove them from the list and send a message back to Kad so we can send a ACK.
	//If we don't connect, we need to remove the client..
	//The sockets timeout should delete this object.

	// buddy is just a flag that is used to make sure we are still connected or connecting to a buddy.
	buddyState buddy = Disconnected;

	CClientRefSet::iterator current_it = m_KadSources.begin();
	while (current_it != m_KadSources.end()) {
		CUpDownClient* cur_client = current_it->GetClient();
		++current_it; // Won't be used anymore till while loop
		if( !Kademlia::CKademlia::IsRunning() ) {
			//Clear out this list if we stop running Kad.
			//Setting the Kad state to KS_NONE causes it to be removed in the switch below.
			cur_client->SetKadState(KS_NONE);
		}
		switch (cur_client->GetKadState()) {
			case KS_QUEUED_FWCHECK:
			case KS_QUEUED_FWCHECK_UDP:
				//Another client asked us to try to connect to them to check their firewalled status.
				cur_client->TryToConnect(true);
				break;

			case KS_CONNECTING_FWCHECK:
				//Ignore this state as we are just waiting for results.
				break;

			case KS_FWCHECK_UDP:
			case KS_CONNECTING_FWCHECK_UDP:
				// We want a UDP firewallcheck from this client and are just waiting to get connected to send the request
				break;

			case KS_CONNECTED_FWCHECK:
				//We successfully connected to the client.
				//We now send a ack to let them know.
				if (cur_client->GetKadVersion() >= 7) {
					// The result is now sent per TCP instead of UDP, because this will fail if our intern port is unreachable.
					// But we want the TCP testresult regardless if UDP is firewalled, the new UDP state and test takes care of the rest
					wxASSERT(cur_client->IsConnected());
					AddDebugLogLineN(logLocalClient, wxT("Local Client: OP_KAD_FWTCPCHECK_ACK to ") + Uint32toStringIP(cur_client->GetIP()));
					CPacket *packet = new CPacket(OP_KAD_FWTCPCHECK_ACK, 0, OP_EMULEPROT);
					cur_client->SafeSendPacket(packet);
				} else {
					AddDebugLogLineN(logClientKadUDP, wxT("KadFirewalledAckRes to ") + Uint32_16toStringIP_Port(cur_client->GetIP(), cur_client->GetKadPort()));
					Kademlia::CKademlia::GetUDPListener()->SendNullPacket(KADEMLIA_FIREWALLED_ACK_RES, wxUINT32_SWAP_ALWAYS(cur_client->GetIP()), cur_client->GetKadPort(), 0, NULL);
				}
				//We are done with this client. Set Kad status to KS_NONE and it will be removed in the next cycle.
				cur_client->SetKadState(KS_NONE);
				break;

			case KS_INCOMING_BUDDY:
				//A firewalled client wants us to be his buddy.
				//If we already have a buddy, we set Kad state to KS_NONE and it's removed in the next cycle.
				//If not, this client will change to KS_CONNECTED_BUDDY when it connects.
				if( m_nBuddyStatus == Connected ) {
					cur_client->SetKadState(KS_NONE);
				}
				break;

			case KS_QUEUED_BUDDY:
				//We are firewalled and want to request this client to be a buddy.
				//But first we check to make sure we are not already trying another client.
				//If we are not already trying. We try to connect to this client.
				//If we are already connected to a buddy, we set this client to KS_NONE and it's removed next cycle.
				//If we are trying to connect to a buddy, we just ignore as the one we are trying may fail and we can then try this one.
				if( m_nBuddyStatus == Disconnected ) {
					buddy = Connecting;
					m_nBuddyStatus = Connecting;
					cur_client->SetKadState(KS_CONNECTING_BUDDY);
					cur_client->TryToConnect(true);
					Notify_ServerUpdateED2KInfo();
				} else {
					if( m_nBuddyStatus == Connected ) {
						cur_client->SetKadState(KS_NONE);
					}
				}
				break;

			case KS_CONNECTING_BUDDY:
				//We are trying to connect to this client.
				//Although it should NOT happen, we make sure we are not already connected to a buddy.
				//If we are we set to KS_NONE and it's removed next cycle.
				//But if we are not already connected, make sure we set the flag to connecting so we know
				//things are working correctly.
				if( m_nBuddyStatus == Connected ) {
					cur_client->SetKadState(KS_NONE);
				} else {
					wxASSERT( m_nBuddyStatus == Connecting );
					buddy = Connecting;
				}
				break;

			case KS_CONNECTED_BUDDY:
				//A potential connected buddy client wanting to me in the Kad network
				//We set our flag to connected to make sure things are still working correctly.
				buddy = Connected;

				//If m_nBuddyStatus is not connected already, we set this client as our buddy!
				if( m_nBuddyStatus != Connected ) {
					m_pBuddy.Link(cur_client CLIENT_DEBUGSTRING("CClientList::Process KS_CONNECTED_BUDDY m_pBuddy.Link"));
					m_nBuddyStatus = Connected;
					Notify_ServerUpdateED2KInfo();
				}
				if( m_pBuddy.GetClient() == cur_client && theApp->IsFirewalled() && cur_client->SendBuddyPingPong() ) {
					cur_client->SendBuddyPing();
				}
				break;

			default:
				RemoveFromKadList(cur_client);
		}
	}

	//We either never had a buddy, or lost our buddy..
	if( buddy == Disconnected ) {
		if( m_nBuddyStatus != Disconnected || m_pBuddy.IsLinked() ) {
			if( Kademlia::CKademlia::IsRunning() && theApp->IsFirewalled() && Kademlia::CUDPFirewallTester::IsFirewalledUDP(true) ) {
				//We are a lowID client and we just lost our buddy.
				//Go ahead and instantly try to find a new buddy.
				Kademlia::CKademlia::GetPrefs()->SetFindBuddy();
			}
			m_pBuddy.Unlink();
			m_nBuddyStatus = Disconnected;
			Notify_ServerUpdateED2KInfo();
		}
	}

	if ( Kademlia::CKademlia::IsConnected() ) {
		// we only need a buddy if direct callback is not available
		if(Kademlia::CKademlia::IsFirewalled() && Kademlia::CUDPFirewallTester::IsFirewalledUDP(true)) {
			// TODO: Kad buddies won't work with RequireCrypt, so it is disabled for now, but should (and will)
			// be fixed in later version
			// Update: buddy connections themselves support obfuscation properly since eMule 0.49a and aMule SVN 2008-05-09
			// (this makes it work fine if our buddy uses require crypt), however callback requests don't support it yet so we
			// wouldn't be able to answer callback requests with RequireCrypt, protocolchange intended for eMule 0.49b
			if(m_nBuddyStatus == Disconnected && Kademlia::CKademlia::GetPrefs()->GetFindBuddy() && !thePrefs::IsClientCryptLayerRequired()) {
				AddDebugLogLineN(logKadMain, wxT("Starting BuddySearch"));
				//We are a firewalled client with no buddy. We have also waited a set time
				//to try to avoid a false firewalled status.. So lets look for a buddy..
				if (!Kademlia::CSearchManager::PrepareLookup(Kademlia::CSearch::FINDBUDDY, true, Kademlia::CUInt128(true) ^ (Kademlia::CKademlia::GetPrefs()->GetKadID()))) {
					//This search ID was already going. Most likely reason is that
					//we found and lost our buddy very quickly and the last search hadn't
					//had time to be removed yet. Go ahead and set this to happen again
					//next time around.
					Kademlia::CKademlia::GetPrefs()->SetFindBuddy();
				}
			}
		} else {
			if (m_pBuddy.IsLinked()) {
				//Lets make sure that if we have a buddy, they are firewalled!
				//If they are also not firewalled, then someone must have fixed their firewall or stopped saturating their line..
				//We just set the state of this buddy to KS_NONE and things will be cleared up with the next cycle.
				if( !m_pBuddy.HasLowID() ) {
					m_pBuddy.GetClient()->SetKadState(KS_NONE);
				}
			}
		}
	} else {
		if (m_pBuddy.IsLinked()) {
			//We are not connected anymore. Just set this buddy to KS_NONE and things will be cleared out on next cycle.
			m_pBuddy.GetClient()->SetKadState(KS_NONE);
		}
	}

	CleanUpClientList();
	ProcessDirectCallbackList();
}