📄 discoveryservices.cpp
字号:
//////////////////////////////////////////////////////////////////////
// CDiscoveryServices thread bootstrap
UINT CDiscoveryServices::ThreadStart(LPVOID pParam)
{
CDiscoveryServices* pClass = (CDiscoveryServices*)pParam;
pClass->OnRun();
return 0;
}
//////////////////////////////////////////////////////////////////////
// CDiscoveryServices thread run
void CDiscoveryServices::OnRun()
{
BOOL bSuccess = TRUE;
if ( m_nWebCache == wcmServerMet )
{
bSuccess = RunServerMet();
}
else if ( m_nWebCache == wcmHosts )
{
bSuccess = RunWebCacheGet( FALSE );
if ( bSuccess && m_hInternet )
{
CSingleLock pLock( &Network.m_pSection, TRUE );
if ( m_bFirstTime || ( GetCount( CDiscoveryService::dsWebCache ) < (int)Settings.Discovery.Lowpoint ) )
{
m_bFirstTime = FALSE;
pLock.Unlock();
bSuccess = RunWebCacheGet( TRUE );
}
}
}
else if ( m_nWebCache == wcmCaches )
{
bSuccess = RunWebCacheGet( TRUE );
}
else if ( m_nWebCache == wcmUpdate )
{
bSuccess = RunWebCacheUpdate();
if ( ! bSuccess ) m_tUpdated = 0;
}
else if ( m_nWebCache == wcmSubmit )
{
bSuccess = RunWebCacheUpdate();
}
if ( m_hInternet && ! bSuccess )
{
CSingleLock pLock( &Network.m_pSection );
if ( pLock.Lock( 250 ) && Check( m_pWebCache ) ) m_pWebCache->OnFailure();
}
if ( m_hInternet != NULL )
{
if ( m_hRequest != NULL ) InternetCloseHandle( m_hRequest );
InternetCloseHandle( m_hInternet );
m_hInternet = NULL;
m_hRequest = NULL;
}
}
//////////////////////////////////////////////////////////////////////
// CDiscoveryServices execute hosts request
BOOL CDiscoveryServices::RunWebCacheGet(BOOL bCaches)
{
CSingleLock pLock( &Network.m_pSection, TRUE );
CString strURL, strOutput;
if ( ! Check( m_pWebCache ) ) return FALSE;
m_pWebCache->OnAccess();
if ( bCaches )
strURL = m_pWebCache->m_sAddress + _T("?get=1&urlfile=1");
else
strURL = m_pWebCache->m_sAddress + _T("?get=1&hostfile=1");
if ( m_bForG2 ) strURL += _T("&net=gnutella2");
pLock.Unlock();
if ( ! SendWebCacheRequest( strURL, strOutput ) ) return FALSE;
pLock.Lock();
if ( ! Check( m_pWebCache ) ) return FALSE;
BOOL bSuccess = FALSE;
int nIP[4], nIPs = 0;
for ( strOutput += '\n' ; strOutput.GetLength() ; )
{
CString strLine = strOutput.SpanExcluding( _T("\r\n") );
strOutput = strOutput.Mid( strLine.GetLength() + 1 );
strLine.TrimLeft();
strLine.TrimRight();
if ( strLine.IsEmpty() ) continue;
theApp.Message( MSG_DEBUG, _T("GWebCache(get): %s"), (LPCTSTR)strLine );
if ( _tcsnicmp( strLine, _T("h|"), 2 ) == 0 )
{
// IP ADDRESS AT: strLine.Mid( 2 )
// CORRECT (REQUESTED) NETWORK
strLine = strLine.Mid( 2 );
int nBreak = strLine.Find( '|' );
DWORD tSeen = 0;
if ( nBreak > 0 )
{
int nSeconds = 0;
_stscanf( strLine.Mid( nBreak + 1 ), _T("%lu"), &nSeconds );
nSeconds = max( 0, min( 18000, nSeconds ) );
strLine = strLine.Left( nBreak );
tSeen = time( NULL ) - nSeconds;
}
if ( m_bForG2 )
HostCache.Gnutella2.Add( strLine, tSeen );
else
HostCache.Gnutella1.Add( strLine, tSeen );
m_pWebCache->OnHostAdd();
m_pWebCache->m_bGnutella2 = TRUE;
bSuccess = TRUE;
nIPs ++;
}
else if ( _tcsnicmp( strLine, _T("u|"), 2 ) == 0 )
{
// URL ADDRESS AT: strLine.Mid( 2 )
// CORRECT (REQUESTED) NETWORK
Add( strLine.Mid( 2 ).SpanExcluding( _T("|") ), CDiscoveryService::dsWebCache, m_bForG2 );
m_pWebCache->m_bGnutella2 = TRUE;
m_bFirstTime = FALSE;
bSuccess = TRUE;
}
else if ( _tcsnicmp( strLine, _T("i|"), 2 ) == 0 )
{
// INFORMATIONAL
bSuccess = TRUE;
m_pWebCache->m_bGnutella2 = TRUE;
if ( _tcsnicmp( strLine, _T("i|access|period|"), 16 ) == 0 )
{
_stscanf( (LPCTSTR)strLine + 16, _T("%lu"), &m_pWebCache->m_nAccessPeriod );
}
else if ( strLine == _T("i|force|remove") )
{
m_pWebCache->Remove();
return FALSE;
}
if ( _tcsistr( strLine, _T("ERROR") ) != NULL )
{
// ERROR CONDITION
return FALSE;
}
}
else if ( _tcsistr( strLine, _T("ERROR") ) != NULL )
{
// ERROR CONDITION
return FALSE;
}
else if ( _stscanf( strLine, _T("%i.%i.%i.%i"), &nIP[0], &nIP[1], &nIP[2], &nIP[3] ) == 4 )
{
// Plain IP, NOT G2
HostCache.Gnutella1.Add( strLine );
m_pWebCache->OnHostAdd();
m_pWebCache->m_bGnutella2 = FALSE;
bSuccess = TRUE;
}
else
{
// Plain URL, WRONG NETWORK
Add( strLine.SpanExcluding( _T(" ") ), CDiscoveryService::dsWebCache, FALSE );
m_pWebCache->m_bGnutella2 = FALSE;
m_bFirstTime = FALSE;
}
}
if ( bSuccess )
{
m_pWebCache->OnSuccess();
if ( HostCache.Gnutella2.GetNewest() != NULL && nIPs > 0 ) m_tQueried = time( NULL );
return TRUE;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CDiscoveryServices execute update request
BOOL CDiscoveryServices::RunWebCacheUpdate()
{
CSingleLock pLock( &Network.m_pSection, TRUE );
CString strURL, strOutput;
if ( ! Check( m_pWebCache, CDiscoveryService::dsWebCache ) ) return FALSE;
m_pWebCache->OnAccess();
if ( m_nWebCache == wcmUpdate )
{
if ( ! Network.IsListening() ) return TRUE;
strURL.Format( _T("%s?update=1&ip=%s:%lu&x.leaves=%lu"),
(LPCTSTR)m_pWebCache->m_sAddress,
(LPCTSTR)CString( inet_ntoa( Network.m_pHost.sin_addr ) ),
htons( Network.m_pHost.sin_port ),
Neighbours.GetCount( -1, -1, ntLeaf ) );
}
if ( m_pSubmit != NULL && Check( m_pSubmit, CDiscoveryService::dsWebCache ) &&
m_pWebCache->m_bGnutella2 == m_pSubmit->m_bGnutella2 )
{
if ( strURL.IsEmpty() )
{
strURL.Format( _T("%s?url="), (LPCTSTR)m_pWebCache->m_sAddress );
}
else
{
strURL += _T("&url=");
}
CString strSubmit( m_pSubmit->m_sAddress );
for ( int nSubmit = 0 ; nSubmit < strSubmit.GetLength() ; nSubmit ++ )
{
if ( (WORD)strSubmit.GetAt( nSubmit ) > 127 )
{
strSubmit = strSubmit.Left( nSubmit );
break;
}
}
strURL += CConnection::URLEncode( strSubmit );
}
if ( Settings.Gnutella2.EnableToday ) strURL += _T("&net=gnutella2");
pLock.Unlock();
if ( strURL.IsEmpty() ) return FALSE;
if ( ! SendWebCacheRequest( strURL, strOutput ) ) return FALSE;
pLock.Lock();
if ( ! Check( m_pWebCache, CDiscoveryService::dsWebCache ) ) return FALSE;
for ( strOutput += '\n' ; strOutput.GetLength() ; )
{
CString strLine = strOutput.SpanExcluding( _T("\r\n") );
strOutput = strOutput.Mid( strLine.GetLength() + 1 );
strLine.TrimLeft();
strLine.TrimRight();
if ( strLine.IsEmpty() ) continue;
theApp.Message( MSG_DEBUG, _T("GWebCache(update): %s"), (LPCTSTR)strLine );
if ( _tcsstr( strLine, _T("OK") ) )
{
m_pWebCache->m_tUpdated = (DWORD)time( NULL );
m_pWebCache->m_nUpdates++;
m_pWebCache->OnSuccess();
return TRUE;
}
else if ( _tcsstr( strLine, _T("ERROR") ) )
{
return FALSE;
}
else if ( _tcsnicmp( strLine, _T("i|access|period|"), 16 ) == 0 )
{
_stscanf( (LPCTSTR)strLine + 16, _T("%lu"), &m_pWebCache->m_nAccessPeriod );
}
else if ( _tcsnicmp( strLine, _T("i|update|period|"), 16 ) == 0 )
{
_stscanf( (LPCTSTR)strLine + 16, _T("%lu"), &m_pWebCache->m_nUpdatePeriod );
}
else if ( strLine == _T("i|force|remove") )
{
m_pWebCache->Remove();
break;
}
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CDiscoveryServices HTTP request controllor
BOOL CDiscoveryServices::SendWebCacheRequest(CString strURL, CString& strOutput)
{
strOutput.Empty();
strURL += _T("&client=RAZA&version=");
strURL += theApp.m_sVersion;
theApp.Message( MSG_DEBUG, _T("DiscoveryService URL: %s"), (LPCTSTR)strURL );
if ( m_hRequest ) InternetCloseHandle( m_hRequest );
m_hRequest = InternetOpenUrl( m_hInternet, strURL, _T("Connection: close"), -1,
INTERNET_FLAG_RELOAD|INTERNET_FLAG_DONT_CACHE|INTERNET_FLAG_NO_COOKIES, 0 );
if ( m_hRequest == NULL ) return FALSE;
DWORD nStatusCode = 0, nStatusLen = 32;
TCHAR szStatusCode[32];
if ( ! HttpQueryInfo( m_hRequest, HTTP_QUERY_STATUS_CODE, szStatusCode,
&nStatusLen, NULL ) ) return FALSE;
_stscanf( szStatusCode, _T("%lu"), &nStatusCode );
if ( nStatusCode < 200 || nStatusCode > 299 ) return FALSE;
DWORD nRemaining, nResponse = 0;
LPBYTE pResponse = NULL;
while ( InternetQueryDataAvailable( m_hRequest, &nRemaining, 0, 0 ) && nRemaining > 0 )
{
pResponse = (LPBYTE)realloc( pResponse, nResponse + nRemaining );
InternetReadFile( m_hRequest, pResponse + nResponse, nRemaining, &nRemaining );
nResponse += nRemaining;
}
if ( nRemaining )
{
free( pResponse );
return FALSE;
}
LPTSTR pszResponse = strOutput.GetBuffer( nResponse );
for ( nStatusCode = 0 ; nStatusCode < nResponse ; nStatusCode++ )
pszResponse[ nStatusCode ] = (TCHAR)pResponse[ nStatusCode ];
strOutput.ReleaseBuffer( nResponse );
free( pResponse );
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CDiscoveryServices execute server.met request
BOOL CDiscoveryServices::RunServerMet()
{
CSingleLock pLock( &Network.m_pSection, TRUE );
CString strURL;
if ( ! Check( m_pWebCache, CDiscoveryService::dsServerMet ) ) return FALSE;
m_pWebCache->OnAccess();
strURL = m_pWebCache->m_sAddress;
pLock.Unlock();
if ( m_hRequest != NULL ) InternetCloseHandle( m_hRequest );
m_hRequest = InternetOpenUrl( m_hInternet, strURL, NULL, 0,
INTERNET_FLAG_RELOAD|INTERNET_FLAG_DONT_CACHE, 0 );
if ( m_hRequest == NULL ) return FALSE;
DWORD nRemaining = 0;
BYTE pBuffer[1024];
CMemFile pFile;
while ( InternetQueryDataAvailable( m_hRequest, &nRemaining, 0, 0 ) && nRemaining > 0 )
{
while ( nRemaining > 0 )
{
DWORD nBuffer = min( nRemaining, 1024 );
InternetReadFile( m_hRequest, pBuffer, nBuffer, &nBuffer );
pFile.Write( pBuffer, nBuffer );
nRemaining -= nBuffer;
}
}
pFile.Seek( 0, CFile::begin );
pLock.Lock();
if ( ! Check( m_pWebCache, CDiscoveryService::dsServerMet ) ) return FALSE;
int nCount = HostCache.eDonkey.ImportMET( &pFile );
if ( ! nCount ) return FALSE;
HostCache.Save();
m_pWebCache->OnHostAdd( nCount );
m_pWebCache->OnSuccess();
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CDiscoveryService construction
CDiscoveryService::CDiscoveryService(int nType, LPCTSTR pszAddress)
{
m_nType = nType;
m_bGnutella2 = FALSE;
m_tCreated = (DWORD)time( NULL );
m_tAccessed = 0;
m_nAccesses = 0;
m_tUpdated = 0;
m_nUpdates = 0;
m_nFailures = 0;
m_nHosts = 0;
m_nAccessPeriod = max( Settings.Discovery.UpdatePeriod, 1800 );
m_nUpdatePeriod = Settings.Discovery.DefaultUpdate;
if ( pszAddress != NULL ) m_sAddress = pszAddress;
}
CDiscoveryService::~CDiscoveryService()
{
}
//////////////////////////////////////////////////////////////////////
// CDiscoveryService remove
void CDiscoveryService::Remove()
{
DiscoveryServices.Remove( this );
}
//////////////////////////////////////////////////////////////////////
// CDiscoveryService serialize
void CDiscoveryService::Serialize(CArchive& ar, int nVersion)
{
if ( ar.IsStoring() )
{
ar << m_nType;
ar << m_sAddress;
ar << m_bGnutella2;
ar << m_tCreated;
ar << m_tAccessed;
ar << m_nAccesses;
ar << m_tUpdated;
ar << m_nUpdates;
ar << m_nFailures;
ar << m_nHosts;
ar << m_nAccessPeriod;
ar << m_nUpdatePeriod;
}
else
{
ar >> m_nType;
ar >> m_sAddress;
ar >> m_bGnutella2;
ar >> m_tCreated;
ar >> m_tAccessed;
ar >> m_nAccesses;
ar >> m_tUpdated;
ar >> m_nUpdates;
ar >> m_nFailures;
ar >> m_nHosts;
ar >> m_nAccessPeriod;
ar >> m_nUpdatePeriod;
}
}
//////////////////////////////////////////////////////////////////////
// CDiscoveryService execute
BOOL CDiscoveryService::Execute(int nMode)
{
CSingleLock pLock( &Network.m_pSection );
if ( ! pLock.Lock( 250 ) ) return FALSE;
if ( nMode != CDiscoveryServices::wcmSubmit )
{
theApp.Message( MSG_SYSTEM, IDS_DISCOVERY_QUERY, (LPCTSTR)m_sAddress );
}
else
{
theApp.Message( MSG_SYSTEM, IDS_DISCOVERY_SUBMIT, (LPCTSTR)m_sAddress );
}
if ( m_nType == dsGnutella )
{
return ResolveGnutella();
}
else if ( m_nType == dsWebCache )
{
return DiscoveryServices.RequestWebCache( this, nMode );
}
else if ( m_nType == dsServerMet )
{
return DiscoveryServices.RequestWebCache( this, CDiscoveryServices::wcmServerMet );
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CDiscoveryService resolve a gnutella node
BOOL CDiscoveryService::ResolveGnutella()
{
CString strHost = m_sAddress;
int nPort = GNUTELLA_DEFAULT_PORT;
int nPos = strHost.Find( ':' );
if ( nPos >= 0 && _stscanf( strHost.Mid( nPos + 1 ), _T("%i"), &nPort ) == 1 )
strHost = strHost.Left( nPos );
if ( ! Network.Connect( FALSE ) ) return FALSE;
if ( Network.AsyncResolve( strHost, (WORD)nPort, PROTOCOL_G1, 0 ) )
{
OnSuccess();
return TRUE;
}
OnFailure();
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CDiscoveryService events
void CDiscoveryService::OnAccess()
{
m_tAccessed = (DWORD)time( NULL );
m_nAccesses ++;
}
void CDiscoveryService::OnHostAdd(int nCount)
{
m_nHosts += nCount;
m_nFailures = 0;
}
void CDiscoveryService::OnSuccess()
{
m_nFailures = 0;
if ( m_nType == dsWebCache || m_nType == dsServerMet )
{
theApp.Message( MSG_DEFAULT, IDS_DISCOVERY_WEB_SUCCESS,
(LPCTSTR)m_sAddress );
}
}
void CDiscoveryService::OnFailure()
{
m_nFailures++;
theApp.Message( MSG_ERROR, IDS_DISCOVERY_FAILED,
(LPCTSTR)m_sAddress, m_nFailures );
if ( m_nFailures >= Settings.Discovery.FailureLimit )
{
theApp.Message( MSG_ERROR, IDS_DISCOVERY_FAIL_REMOVE,
(LPCTSTR)m_sAddress, m_nFailures );
Remove();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -