示例#1
0
void CMuleUDPSocket::SendPacket(CPacket* packet, uint32 IP, uint16 port, bool bEncrypt, const uint8* pachTargetClientHashORKadID, bool bKad, uint32 nReceiverVerifyKey)
{
	wxCHECK_RET(packet, wxT("Invalid packet."));
	/*wxCHECK_RET(port, wxT("Invalid port."));
	wxCHECK_RET(IP, wxT("Invalid IP."));
	*/

	if (!port || !IP) {
		return;
	}

	if (!Ok()) {
		AddDebugLogLineN(logMuleUDP, (m_name + wxT(": Packet discarded, socket not Ok ("))
			<< Uint32_16toStringIP_Port(IP, port) << wxT("): ") << packet->GetPacketSize() << wxT("b"));
		delete packet;

		return;
	}

	AddDebugLogLineN(logMuleUDP, (m_name + wxT(": Packet queued ("))
		<< Uint32_16toStringIP_Port(IP, port) << wxT("): ") << packet->GetPacketSize() << wxT("b"));

	UDPPack newpending;
	newpending.IP = IP;
	newpending.port = port;
	newpending.packet = packet;
	newpending.time = GetTickCount();
	newpending.bEncrypt = bEncrypt && (pachTargetClientHashORKadID != NULL || (bKad && nReceiverVerifyKey != 0))
							&& thePrefs::IsClientCryptLayerSupported();
	newpending.bKad = bKad;
	newpending.nReceiverVerifyKey = nReceiverVerifyKey;
	if (newpending.bEncrypt && pachTargetClientHashORKadID != NULL) {
		md4cpy(newpending.pachTargetClientHashORKadID, pachTargetClientHashORKadID);
	} else {
		md4clr(newpending.pachTargetClientHashORKadID);
	}

	{
		wxMutexLocker lock(m_mutex);
		m_queue.push_back(newpending);
	}

	theApp->uploadBandwidthThrottler->QueueForSendingControlPacket(this);
}
示例#2
0
bool CMuleUDPSocket::SendTo(uint8_t *buffer, uint32_t length, uint32_t ip, uint16_t port)
{
	// Just pretend that we sent the packet in order to avoid infinite loops.
	if (!(m_socket && m_socket->Ok())) {
		return true;
	}
	
	amuleIPV4Address addr;
	addr.Hostname(ip);
	addr.Service(port);

	// We better clear this flag here, status might have been changed
	// between the U.B.T. addition and the real sending happening later
	m_busy = false; 
	bool sent = false;
	m_socket->SendTo(addr, buffer, length);
	if (m_socket->Error()) {
		wxSocketError error = m_socket->LastError();
		
		if (error == wxSOCKET_WOULDBLOCK) {
			// Socket is busy and can't send this data right now,
			// so we just return not sent and set the wouldblock 
			// flag so it gets resent when socket is ready.
			m_busy = true;
		} else {
			// An error which we can't handle happended, so we drop 
			// the packet rather than risk entering an infinite loop.
			AddLogLineN((wxT("WARNING! ") + m_name + wxT(": Packet to ")) 
				<< Uint32_16toStringIP_Port(ip, port)
				<< wxT(" discarded due to error (") << error << wxT(") while sending."));
			sent = true;
		}
	} else {
		AddDebugLogLineN(logMuleUDP, (m_name + wxT(": Packet sent ("))
			<< Uint32_16toStringIP_Port(ip, port) << wxT("): ")
			<< length << wxT("b"));
		sent = true;
	}

	return sent;
}
示例#3
0
void CServerWnd::UpdateED2KInfo()
{
	wxListCtrl* ED2KInfoList = CastChild( ID_ED2KINFO, wxListCtrl );
	
	ED2KInfoList->DeleteAllItems();
	ED2KInfoList->InsertItem(0, _("eD2k Status:"));

	if (theApp->IsConnectedED2K()) {
		ED2KInfoList->SetItem(0, 1, _("Connected"));

		// Connection data		
		
		ED2KInfoList->InsertItem(1, _("IP:Port"));
		ED2KInfoList->SetItem(1, 1, theApp->serverconnect->IsLowID() ? 
			 wxString(_("LowID")) : Uint32_16toStringIP_Port( theApp->GetED2KID(), thePrefs::GetPort()));

		ED2KInfoList->InsertItem(2, _("ID"));
		// No need to test the server connect, it's already true
		ED2KInfoList->SetItem(2, 1, CFormat(wxT("%u")) % theApp->GetED2KID());
		
		ED2KInfoList->InsertItem(3, wxEmptyString);		

		if (theApp->serverconnect->IsLowID()) {
			ED2KInfoList->SetItem(1, 1, _("Server")); // LowID, unknown ip
			ED2KInfoList->SetItem(3, 1, _("LowID"));
		} else {
			ED2KInfoList->SetItem(1, 1, Uint32_16toStringIP_Port(theApp->GetED2KID(), thePrefs::GetPort()));
			ED2KInfoList->SetItem(3, 1, _("HighID"));
		}
		
	} else {
		// No data
		ED2KInfoList->SetItem(0, 1, _("Not Connected"));
	}

	// Fit the width of the columns
	ED2KInfoList->SetColumnWidth(0, -1);
	ED2KInfoList->SetColumnWidth(1, -1);
}
示例#4
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);
	}
}
示例#5
0
void CServerWnd::UpdateKadInfo()
{
	wxListCtrl* KadInfoList = CastChild( ID_KADINFO, wxListCtrl );

	int next_row = 0;

	KadInfoList->DeleteAllItems();

	KadInfoList->InsertItem(next_row, _("Kademlia Status:"));

	if (theApp->IsKadRunning()) {
		KadInfoList->SetItem(next_row++, 1, (theApp->IsKadRunningInLanMode() ? _("Running in LAN mode") : _("Running")));

		// Connection data
		KadInfoList->InsertItem(next_row, _("Status:"));
		KadInfoList->SetItem(next_row++, 1, theApp->IsConnectedKad() ? _("Connected"): _("Disconnected"));
		if (theApp->IsConnectedKad()) {
			KadInfoList->InsertItem(next_row, _("Connection State:"));
			KadInfoList->SetItem(next_row++, 1, theApp->IsFirewalledKad() ?
				wxString(CFormat(_("Firewalled - open TCP port %d in your router or firewall")) % thePrefs::GetPort())
				: wxString(_("OK")));
			KadInfoList->InsertItem(next_row, _("UDP Connection State:"));
			bool UDPFirewalled = theApp->IsFirewalledKadUDP();
			KadInfoList->SetItem(next_row++, 1, UDPFirewalled ?
				wxString(CFormat(_("Firewalled - open UDP port %d in your router or firewall")) % thePrefs::GetUDPPort())
				: wxString(_("OK")));

			if (theApp->IsFirewalledKad() || UDPFirewalled) {
				KadInfoList->InsertItem(next_row, _("Firewalled state: "));
				wxString BuddyState;
				switch ( theApp->GetBuddyStatus() )
				{
					case Disconnected:
						if (!theApp->IsFirewalledKad()) {
							BuddyState = _("No buddy required - TCP port open");
						} else if (!UDPFirewalled) {
							BuddyState = _("No buddy required - UDP port open");
						} else {
							BuddyState = _("No buddy");
						}
						break;
					case Connecting:
						BuddyState = _("Connecting to buddy");
						break;
					case Connected:
						BuddyState = CFormat(_("Connected to buddy at %s")) % Uint32_16toStringIP_Port(theApp->GetBuddyIP(), theApp->GetBuddyPort());
						break;
				}
				KadInfoList->SetItem(next_row++, 1, BuddyState);
			}

			KadInfoList->InsertItem(next_row, _("IP address:"));
			KadInfoList->SetItem(next_row++, 1, Uint32toStringIP(theApp->GetKadIPAdress()));

			// Index info
			KadInfoList->InsertItem(next_row, _("Indexed sources:"));
			KadInfoList->SetItem(next_row++, 1, CFormat(wxT("%d")) % theApp->GetKadIndexedSources());
			KadInfoList->InsertItem(next_row, _("Indexed keywords:"));
			KadInfoList->SetItem(next_row++, 1, CFormat(wxT("%d")) % theApp->GetKadIndexedKeywords());
			KadInfoList->InsertItem(next_row, _("Indexed notes:"));
			KadInfoList->SetItem(next_row++, 1, CFormat(wxT("%d")) % theApp->GetKadIndexedNotes());
			KadInfoList->InsertItem(next_row, _("Indexed load:"));
			KadInfoList->SetItem(next_row++, 1, CFormat(wxT("%d")) % theApp->GetKadIndexedLoad());

			KadInfoList->InsertItem(next_row, _("Average Users:"));
			KadInfoList->SetItem(next_row, 1, CastItoIShort(theApp->GetKadUsers()));
			++next_row;
			KadInfoList->InsertItem(next_row, _("Average Files:"));
			KadInfoList->SetItem(next_row, 1, CastItoIShort(theApp->GetKadFiles()));
		}
	} else {
		// No data
		KadInfoList->SetItem(next_row, 1, _("Not running"));
	}

	// Fit the width of the columns
	KadInfoList->SetColumnWidth(0, -1);
	KadInfoList->SetColumnWidth(1, -1);
}
示例#6
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();
}