Beispiel #1
0
void CEDClients::OnRun()
{
	DWORD tNow = GetTickCount();

	// Delay to limit the rate of ed2k packets being sent.
	// Keep ed2k transfers under 10 KB/s per source
	if ( tNow < m_tLastRun + Settings.eDonkey.PacketThrottle )
		return;

	CSingleLock oCEDClientsLock( &m_pSection );
	if ( ! oCEDClientsLock.Lock( 250 ) )
		return;

	CSingleLock oCTransfersLock( &Transfers.m_pSection );
	if ( ! oCTransfersLock.Lock( 250 ) )
		return;

	tNow = GetTickCount();	// Update

	if ( Settings.eDonkey.ServerWalk &&
		 Network.IsConnected() &&
		 Settings.eDonkey.Enabled )
		RunGlobalStatsRequests( tNow );

	for ( CEDClient* pClient = m_pFirst ; pClient ; )
	{
		CEDClient* pNext = pClient->m_pEdNext;
		pClient->OnRunEx( tNow );
		pClient = pNext;
	}

	m_tLastRun = tNow;
}
CEDClient* CEDClients::Connect(DWORD nClientID, WORD nClientPort, IN_ADDR* pServerAddress, WORD nServerPort, GGUID* pGUID)
{
	if ( pGUID != NULL )
	{
		if ( CEDClient* pClient = GetByGUID( pGUID ) ) return pClient;
	}
	
	if ( IsFull() ) return NULL;
	
	CEDClient* pClient = NULL;
	
	if ( CEDPacket::IsLowID( nClientID ) )
	{
		if ( pServerAddress == NULL || nServerPort == 0 ) return NULL;
		pClient = GetByID( nClientID, pServerAddress, pGUID );
	}
	else
	{
		if ( Security.IsDenied( (IN_ADDR*)&nClientID ) ) return NULL;
		pClient = GetByID( nClientID, NULL, pGUID );
	}
	
	if ( pClient == NULL )
	{
		pClient = new CEDClient();
		pClient->ConnectTo( nClientID, nClientPort, pServerAddress, nServerPort, pGUID );
	}
	
	return pClient;
}
Beispiel #3
0
bool CEDClients::IsFull(const CEDClient* pCheckThis)
{
	CQuickLock oLock( m_pSection );

	// Count the number of connected clients
	DWORD nCount = 0;
	for ( CEDClient* pClient = m_pFirst ; pClient ; pClient = pClient->m_pEdNext )
	{
		if ( pClient->IsValid() )
			++nCount;
	}

	// Get current time
	const DWORD tNow = GetTickCount();

	// If there are more clients current connected than there should be, set full timer
	if ( nCount >= Settings.eDonkey.MaxLinks )
		m_tLastMaxClients = tNow;

	// If we have not been full in the past 2 seconds, then we're okay to start new connections
	if ( tNow - m_tLastMaxClients > 2ul * 1000ul )
		return false;

	// If we're checking a client that's already connected, say we aren't full. (don't drop it)
	if ( pCheckThis && pCheckThis->IsValid() )
		return false;

	// We're too full to start new connections
	return true;
}
Beispiel #4
0
void CEDClients::OnRun()
{
	DWORD tNow = GetTickCount();

	// Delay to limit the rate of ed2k packets being sent.
	// keep ed2k transfers under 10 KB/s per source
	if ( tNow - m_tLastRun < Settings.eDonkey.PacketThrottle )
		return;

	CSingleLock oCTranfersLock( &Transfers.m_pSection );
	if ( ! oCTranfersLock.Lock( 250 ) )
		return;

	CSingleLock oCEDClientsLock( &m_pSection );
	if ( ! oCEDClientsLock.Lock( 250 ) )
		return;

	for ( CEDClient* pClient = m_pFirst ; pClient ; )
	{
		CEDClient* pNext = pClient->m_pEdNext;
		pClient->OnRunEx( tNow );
		pClient = pNext;
	}

	m_tLastRun = tNow;
}
void CEDClients::Clear()
{
	for ( CEDClient* pClient = m_pFirst ; pClient ; )
	{
		CEDClient* pNext = pClient->m_pEdNext;
		pClient->Remove();
		pClient = pNext;
	}
	
	ASSERT( m_pFirst == NULL );
	ASSERT( m_pLast == NULL );
	ASSERT( m_nCount == 0 );
}
Beispiel #6
0
BOOL CEDClients::IsOverloaded() const
{
	CQuickLock oLock( m_pSection );

	DWORD nCount = 0;

	for ( CEDClient* pClient = m_pFirst ; pClient ; pClient = pClient->m_pEdNext )
	{
		if ( pClient->IsValid() ) nCount++;
	}

	return ( nCount >= ( Settings.eDonkey.MaxLinks + 25 ) );
}
BOOL CEDClients::Merge(CEDClient* pClient)
{
	ASSERT( pClient != NULL );

	for ( CEDClient* pOther = m_pFirst ; pOther ; pOther = pOther->m_pEdNext )
	{
		if ( pOther != pClient && pOther->Equals( pClient ) )
		{
			pClient->Merge( pOther );
			pOther->Remove();
			return TRUE;
		}
	}
	
	return FALSE;
}
Beispiel #8
0
CEDClient* CEDClients::Connect(DWORD nClientID, WORD nClientPort, IN_ADDR* pServerAddress, WORD nServerPort, const Hashes::Guid& oGUID)
{
	CEDClient* pClient = NULL;

	{
		CQuickLock oLock( m_pSection );

		if ( oGUID )
		{
			pClient = GetByGUID( oGUID );
			if ( pClient )
				return pClient;
		}

		if ( IsFull() )
			return NULL;

		if ( CEDPacket::IsLowID( nClientID ) )
		{
			if ( pServerAddress == NULL || nServerPort == 0 )
				return NULL;

			pClient = GetByID( nClientID, pServerAddress, oGUID );
		}
		else
		{
			if ( Security.IsDenied( (IN_ADDR*)&nClientID ) )
				return NULL;

			pClient = GetByID( nClientID, NULL, oGUID );
		}
	}

	if ( pClient == NULL )
	{
		pClient = new CEDClient();
		pClient->ConnectTo( nClientID, nClientPort, pServerAddress, nServerPort, oGUID );
	}

	return pClient;
}
void CEDClients::OnRun()
{

	// Delay to limit the rate of ed2k packets being sent.
	// keep ed2k transfers under 10 KB/s per source
	DWORD tNow = GetTickCount();
	if ( tNow - m_tLastRun < Settings.eDonkey.PacketThrottle ) return;
	m_tLastRun = tNow;

	if ( Settings.eDonkey.ServerWalk && Settings.eDonkey.EnableToday )
	{
		RunGlobalStatsRequests( tNow );
	}
	
	for ( CEDClient* pClient = m_pFirst ; pClient ; )
	{
		CEDClient* pNext = pClient->m_pEdNext;
		pClient->OnRunEx( tNow );
		pClient = pNext;
	}
}
BOOL CEDClients::OnAccept(CConnection* pConnection)
{
	ASSERT( pConnection != NULL );
	
	if ( Settings.Connection.RequireForTransfers && ! Settings.eDonkey.EnableToday )
	{
		theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_DISABLED,
			(LPCTSTR)pConnection->m_sAddress );
		return FALSE;
	}
	
	CSingleLock pLock( &Transfers.m_pSection );
	if ( ! pLock.Lock( 250 ) ) return FALSE;

	if ( IsFull() )
	{
		// Even if we're full, we still need to accept connections from clients we have queued, etc
		if ( ( GetByIP( &pConnection->m_pHost.sin_addr ) == NULL ) || ( IsOverloaded() ) )
		{
			theApp.Message( MSG_DEBUG, _T("Rejecting ed2k connection from %s, max client connections reached."),
				(LPCTSTR)pConnection->m_sAddress );
			return FALSE;
		}
		else 
		{
			theApp.Message( MSG_DEBUG, _T("Accepting ed2k connection from %s despite client connection limit."),
				(LPCTSTR)pConnection->m_sAddress );

		}
	}
	
	CEDClient* pClient = new CEDClient();
	pClient->AttachTo( pConnection );
	
	return TRUE;
}
CPrivateChatFrame* CChatWindows::OpenPrivate(GGUID* pGUID, SOCKADDR_IN* pHost, BOOL bMustPush, PROTOCOLID nProtocol, SOCKADDR_IN* pServer)
{
	CPrivateChatFrame* pFrame = NULL;

	ASSERT ( pHost != NULL );

	if ( ( nProtocol == PROTOCOL_BT ) || ( nProtocol == PROTOCOL_FTP ) )
		return NULL;

	if ( ! MyProfile.IsValid() )
	{
		CString strMessage;
		LoadString( strMessage, IDS_CHAT_NEED_PROFILE );
		if ( AfxMessageBox( strMessage, MB_YESNO|MB_ICONQUESTION ) == IDYES )
			AfxGetMainWnd()->PostMessage( WM_COMMAND, ID_TOOLS_PROFILE );
		return NULL;
	}

	if ( nProtocol == PROTOCOL_ED2K )
	{
		CEDClient* pClient;

		// First, check if it's a low ID user on another server. 
		if ( bMustPush && pServer ) 
		{
			// It's a firewalled user (Low ID). If they are using another server, we 
			// can't (shouldn't) contact them. (It places a heavy load on the ed2k servers)
			CSingleLock pLock1( &Network.m_pSection );
			if ( ! pLock1.Lock( 250 ) ) return NULL;
			if ( Neighbours.Get( &pServer->sin_addr ) == NULL ) return NULL;
			pLock1.Unlock();
		}

		// ED2K chat is handled by the EDClient section. (Transfers)
		// We need to find (or create) an EDClient to handle this chat session, since everything 
		// on ed2k shares a TCP link.

		// First, lock the section to prevent a problem with other threads
		CSingleLock pLock( &Transfers.m_pSection );
		if ( ! pLock.Lock( 250 ) ) return NULL;

		// We need to connect to them, so either find or create an EDClient
		if ( pServer )
			pClient = EDClients.Connect(pHost->sin_addr.S_un.S_addr, pHost->sin_port, &pServer->sin_addr, pServer->sin_port, pGUID );
		else
			pClient = EDClients.Connect(pHost->sin_addr.S_un.S_addr, pHost->sin_port, NULL, 0, pGUID );
		// If we weren't able to create a client (Low-id and no server), then exit.
		if ( ! pClient ) return NULL;
		// Have it connect (if it isn't)
		if ( ! pClient->m_bConnected ) pClient->Connect();
		// Tell it to start a chat session as soon as it's able
		pClient->OpenChat();
		pLock.Unlock();

		// Check for / make active any existing window
		pFrame = FindPrivate( &pHost->sin_addr );
		// Check for an empty frame
		if ( pFrame == NULL )
		{
			if ( bMustPush ) pFrame = FindED2KFrame( pHost->sin_addr.S_un.S_addr, pServer );
			else pFrame = FindED2KFrame( pHost );
		}
		if ( pFrame != NULL ) 
		{
			// Open window if we found one
			CWnd* pParent = pFrame->GetParent();
			if ( pParent->IsIconic() ) pParent->ShowWindow( SW_SHOWNORMAL );
			pParent->BringWindowToTop();
			pParent->SetForegroundWindow();
			// And exit
			return pFrame;
		}
		// Open an empty (blank) chat frame. This is totally unnecessary- The EDClient will open 
		// one as required, but it looks better to open one here.
		pFrame = new CPrivateChatFrame();
		// Set name (Also used to match incoming connection)
		if ( bMustPush && pServer ) // Firewalled user (Low ID)
		{
			pFrame->m_sNick.Format( _T("%lu@%s:%hu"),
			pHost->sin_addr.S_un.S_addr,
			(LPCTSTR)CString( inet_ntoa( pServer->sin_addr ) ),
			pServer->sin_port );
		}
		else	// Regular user (High ID)
		{
			pFrame->m_sNick.Format( _T("%s:%hu"), (LPCTSTR)CString( inet_ntoa( pHost->sin_addr ) ), pHost->sin_port );
		}

		// Open window
		CWnd* pParent = pFrame->GetParent();
		if ( pParent->IsIconic() ) pParent->ShowWindow( SW_SHOWNORMAL );
		pParent->BringWindowToTop();
		pParent->SetForegroundWindow();
		// Put a 'connecting' message in the window
		CString strMessage, strConnecting;
		LoadString( strConnecting, IDS_CHAT_CONNECTING_TO );
		strMessage.Format( strConnecting, pFrame->m_sNick );
		pFrame->OnStatusMessage( 0, strMessage );

		return pFrame;
	}

	if ( pGUID != NULL ) pFrame = FindPrivate( pGUID );
	if ( pFrame == NULL ) pFrame = FindPrivate( &pHost->sin_addr );
	
	if ( pFrame == NULL )
	{
		pFrame = new CPrivateChatFrame();
		pFrame->Initiate( pGUID, pHost, bMustPush );	
	}

	pFrame->PostMessage( WM_COMMAND, ID_CHAT_CONNECT );
	
	CWnd* pParent = pFrame->GetParent();
	if ( pParent->IsIconic() ) pParent->ShowWindow( SW_SHOWNORMAL );
	pParent->BringWindowToTop();
	pParent->SetForegroundWindow();

	return pFrame;
}
Beispiel #12
0
BOOL CHostBrowser::Browse()
{
	CQuickLock oTransfersLock( Transfers.m_pSection );

	m_sAddress = inet_ntoa( m_pAddress );
	m_sServer = protocolAbbr[ ( ( m_nProtocol == PROTOCOL_ANY ) ? PROTOCOL_NULL : m_nProtocol ) ];
	m_pVendor = VendorCache.Lookup( m_sServer );

	switch ( m_nProtocol )
	{
	case PROTOCOL_G2:
		Settings.Gnutella2.Enabled = true;
		break;
	case PROTOCOL_G1:
		Settings.Gnutella1.Enabled = true;
		break;
	case PROTOCOL_ED2K:
		Settings.eDonkey.Enabled = true;
		break;
	case PROTOCOL_DC:
		Settings.DC.Enabled = true;
		break;
	//default:
	}

	// ED2K Clients have their connection controlled by ED2KClient.
	// (One connection used for many things)
	if ( m_nProtocol == PROTOCOL_ED2K )
	{
		// Lock this object until we are finished with it
		CQuickLock oCEDClientsLock( EDClients.m_pSection );

		SOCKADDR_IN* pServer = NULL;	// ToDo: Add push connections
		CEDClient* pClient = EDClients.Connect( m_pAddress.s_addr, m_nPort,
			( pServer ? &pServer->sin_addr : NULL ),
			( pServer ? pServer->sin_port : 0 ), m_oClientID );

		if ( pClient && pClient->m_bConnected )
		{
			// Send browse request
			if ( CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_ASKSHAREDDIRS ) )
				pClient->Send( pPacket );
		}
		else if ( ! pClient || ! pClient->Connect() )
		{
			theApp.Message( MSG_NOTICE, IDS_BROWSE_CANT_CONNECT_TO, (LPCTSTR)m_sAddress );
			return FALSE;
		}
	}
	else if ( m_nProtocol == PROTOCOL_DC )
	{
		CEnvyURL oURL;
		oURL.m_nProtocol		= PROTOCOL_DC;
		oURL.m_nAction			= CEnvyURL::uriDownload;
		oURL.m_pServerAddress	= m_pAddress;
		oURL.m_nServerPort		= m_nPort;
		oURL.m_sLogin			= m_sNick;
		oURL.m_sName.Format( L"Files of %s.xml.bz2", (LPCTSTR)SafeFilename( m_sNick ) );
		oURL.m_sURL.Format( L"dchub://%s@%s:%u/files.xml.bz2", (LPCTSTR)URLEncode( m_sNick ), (LPCTSTR)CString( inet_ntoa( m_pAddress ) ), m_nPort );

		return ( Downloads.Add( oURL ) != NULL );
	}
	else // G2/Gunetella
	{
		if ( IsValid() )
			return FALSE;

		if ( m_bMustPush )
		{
			if ( SendPush( FALSE ) )
			{
				theApp.Message( MSG_INFO, IDS_BROWSE_PUSHED_TO, (LPCTSTR)m_sAddress );
			}
			else
			{
				theApp.Message( MSG_NOTICE, IDS_BROWSE_CANT_PUSH_TO, (LPCTSTR)m_sAddress );
				return FALSE;
			}
		}
		else
		{
			if ( ConnectTo( &m_pAddress, m_nPort ) )
			{
				theApp.Message( MSG_INFO, IDS_BROWSE_CONNECTING_TO, (LPCTSTR)m_sAddress );
			}
			else
			{
				theApp.Message( MSG_NOTICE, IDS_BROWSE_CANT_CONNECT_TO, (LPCTSTR)m_sAddress );
				return FALSE;
			}
		}
	}

	m_nState = hbsConnecting;
	m_nHits  = 0;

	delete m_pProfile;
	m_pProfile = NULL;

	// Ensure window text is updated after state has been set to "connecting"
	m_pNotify->UpdateMessages();

	return TRUE;
}
Beispiel #13
0
CPrivateChatWnd* CChatWindows::OpenPrivateED2K(const Hashes::Guid& oGUID, const SOCKADDR_IN* pHost, BOOL bMustPush, SOCKADDR_IN* pServer)
{
	// First, check if it's a low ID user on another server.
	if ( bMustPush && pServer )
	{
		// It's a firewalled user (Low ID). If they are using another server,
		// we can't (shouldn't) contact them. (Places heavy load on ed2k servers)
		CSingleLock pLock1( &Network.m_pSection );
		if ( ! pLock1.Lock( 250 ) ) return NULL;
		if ( Neighbours.Get( pServer->sin_addr ) == NULL ) return NULL;
		pLock1.Unlock();
	}

	// ED2K chat is handled by the EDClient section. (Transfers)
	// We need to find (or create) an EDClient to handle this chat session,
	// since everything on ed2k shares a TCP link.

	// First, lock the section to prevent a problem with other threads
	CSingleLock pLock( &Transfers.m_pSection );
	if ( ! pLock.Lock( 250 ) ) return NULL;

	// We need to connect to them, so either find or create an EDClient
	CEDClient* pClient;
	if ( pServer )
		pClient = EDClients.Connect(pHost->sin_addr.s_addr, ntohs( pHost->sin_port ), &pServer->sin_addr, ntohs( pServer->sin_port ), oGUID );
	else
		pClient = EDClients.Connect(pHost->sin_addr.s_addr, ntohs( pHost->sin_port ), NULL, 0, oGUID );
	// If we weren't able to create a client (Low-id and no server), then exit.
	if ( ! pClient ) return NULL;
	// Have it connect (if it isn't)
	if ( ! pClient->m_bConnected ) pClient->Connect();
	// Tell it to start a chat session as soon as it's able
	pClient->OpenChat();
	pLock.Unlock();

	// Check for / make active any existing window
	CPrivateChatWnd* pFrame = FindPrivate( pHost );
	// Check for an empty frame
	if ( pFrame == NULL )
	{
		if ( bMustPush )
			pFrame = FindED2KFrame( pHost->sin_addr.s_addr, pServer );
		else
			pFrame = FindED2KFrame( pHost );
	}
	if ( pFrame != NULL )
	{
		// Open window if we found one
		//CWnd* pParent = pFrame->GetParent();
		//if ( pParent->IsIconic() ) pParent->ShowWindow( SW_SHOWNORMAL );
		//pParent->BringWindowToTop();
		//pParent->SetForegroundWindow();
		pFrame->Open();

		// And exit
		return pFrame;
	}

	// Set name (Also used to match incoming connection)
	CString strNick;
	if ( bMustPush && pServer )		// Firewalled user (Low ID)
	{
		strNick.Format( L"%lu@%s:%hu",
			pHost->sin_addr.S_un.S_addr,
			(LPCTSTR)CString( inet_ntoa( pServer->sin_addr ) ),
			ntohs( pServer->sin_port ) );
	}
	else	// Regular user (High ID)
	{
		strNick.Format( L"%s:%hu", (LPCTSTR)CString( inet_ntoa( pHost->sin_addr ) ), ntohs( pHost->sin_port ) );
	}

	// Open an empty (blank) chat frame. This is totally unnecessary- The EDClient will open
	// one as required, but it looks better to open one here.
	pFrame = new CPrivateChatWnd();
	pFrame->Setup( strNick );

// Obsolete: for reference & deletion
//	// Open window
//	CWnd* pParent = pFrame->GetParent();
//	if ( pParent->IsIconic() ) pParent->ShowWindow( SW_SHOWNORMAL );
//	pParent->BringWindowToTop();
//	pParent->SetForegroundWindow();
//	// Put a 'connecting' message in the window
//	CString strMessage;
//	strMessage.Format( LoadString( IDS_CHAT_CONNECTING_TO ), (LPCTSTR)pFrame->m_sNick );
//	pFrame->OnStatusMessage( 0, strMessage );
//
//	if ( oGUID )
//		pFrame = FindPrivate( oGUID );
//	if ( pFrame == NULL )
//		pFrame = FindPrivate( &pHost->sin_addr );
//	if ( pFrame == NULL )
//	{
//		pFrame = new CPrivateChatWnd();
//		pFrame->Initiate( oGUID, pHost, bMustPush );
//	}
//
//	pFrame->PostMessage( WM_COMMAND, ID_CHAT_CONNECT );
//
//	CWnd* pParent = pFrame->GetParent();
//	if ( pParent->IsIconic() ) pParent->ShowWindow( SW_SHOWNORMAL );
//	pParent->BringWindowToTop();
//	pParent->SetForegroundWindow();

	return pFrame;
}
BOOL CEDClients::PushTo(DWORD nClientID, WORD nClientPort)
{
	CEDClient* pClient = Connect( nClientID, nClientPort, NULL, 0, NULL );
	if ( pClient == NULL ) return FALSE;
	return pClient->Connect();
}