📄 peercachefinder.cpp
字号:
}
bool CPeerCacheFinder::IsClientPCCompatible(uint32 dwTagVersionInfo, uint16 nClientSoft){
return IsClientPCCompatible(CClientVersionInfo(dwTagVersionInfo, nClientSoft));
}
bool CPeerCacheFinder::IsClientPCCompatible(const CClientVersionInfo& cviToCheck){
CSingleLock lock(&m_SettingsMutex, TRUE);
for (int i = 0; i != liAllowedVersions.GetSize(); i++){
if (cviToCheck < liAllowedVersions[i])
return false;
}
for (int i = 0; i != liBannedVersions.GetSize(); i++){
if (cviToCheck == liBannedVersions[i])
return false;
}
return true;
}
void CPeerCacheFinder::DownloadAttemptFailed(){
m_nFailedDownloads++;
if(m_nDownloadAttempts > 20 && m_nFailedDownloads > 0){
DEBUG_ONLY(AddDebugLogLine(DLP_LOW, false, _T("PeerCache fail value: %0.2f"), (float)(m_nDownloadAttempts/m_nFailedDownloads)));
if ( (float)(m_nDownloadAttempts/m_nFailedDownloads) < (float)2)
AddDebugLogLine(DLP_LOW, false, _T("PeerCache fail value too high, disabling cache downloads"));
}
}
///////////////////////////////////////////////////////////////////////////////////////
/// CPCValditeThread
IMPLEMENT_DYNCREATE(CPCValditeThread, CWinThread)
CPCValditeThread::CPCValditeThread()
{
}
CPCValditeThread::~CPCValditeThread()
{
}
BOOL CPCValditeThread::InitInstance()
{
DbgSetThreadName("PCValditeThread");
InitThreadLocale();
return TRUE;
}
BOOL CPCValditeThread::Run(){
if (theApp.emuledlg != NULL && theApp.emuledlg->IsRunning()){
if (Valdite()){
m_pOwner->m_bValdited = true;
m_pOwner->m_nPCPort = m_nPCPort;
if (m_pOwner->m_PCStatus == PCS_VALDITING){
DEBUG_ONLY(theApp.QueueDebugLogLine(false, _T("PeerCache: Valditing .p2pinfo succeeded")));
DEBUG_ONLY(theApp.QueueLogLine(false, GetResString(IDS_PEERCACHE_ENABLED)));
m_pOwner->m_PCStatus = PCS_READY;
}
else
ASSERT ( false );
}
else{
m_pOwner->m_bValdited = false;
m_pOwner->m_PCStatus = PCS_NOTVERIFIED;
m_pOwner->m_nPCPort = 0;
}
}
return 0;
}
void CPCValditeThread::SetValues(CPeerCacheFinder* in_pOwner, uint32 dwPCIP, uint32 dwMyIP){
m_dwPCIP = dwPCIP;
m_dwMyIP = dwMyIP;
m_pOwner = in_pOwner;
}
bool CPCValditeThread::Valdite(){
ASSERT ( m_dwPCIP != 0 );
ASSERT ( m_dwMyIP != 0 );
CInternetSession session;
CInternetFile* file = NULL;
for (int i = 0; i != ARRSIZE(anPeerCachPorts); i++){
try
{
// try to connect to the URL
CString strURL;
strURL.Format(_T("http://%s:%u/.p2pinfo"), ipstr(m_dwPCIP), anPeerCachPorts[i]);
file = (CInternetFile*)session.OpenURL(strURL);
m_nPCPort = anPeerCachPorts[i];
break;
}
catch (CInternetException* m_pException){
// set file to NULL if there's an error
file = NULL;
m_pException->Delete();
DEBUG_ONLY(theApp.QueueDebugLogLine(false, _T("PeerCache: Failed to retrieve .p2pinfo file on Port %u"),anPeerCachPorts[i]));
if (i == (ARRSIZE(anPeerCachPorts)-1)){ // was last try
DEBUG_ONLY(theApp.QueueDebugLogLine(false, _T("PeerCache: Failed to retrieve .p2pinfo file, cache disabled"),anPeerCachPorts[i]));
return false;
}
}
}
ASSERT( file != NULL );
// TODO: This will work successfully only for very small files which were received completely right at the
// time the 'GetLength' function is called. -> Use a polling loop which reads everything up to get bytes
// specified in 'Content-Length' or some other appropriate limit in case 'Content-Length' is missing.
uint32 nIFileSize = file->GetLength();
ASSERT (nIFileSize > SIGNATURELENGTH);
if (file && nIFileSize > SIGNATURELENGTH){
// read content
CArray<uint32, uint32> adwCacheIPs;
CStringAArray astrIPRanges;
CStringA strLine;
bool bContentCheckFailed = false;
UINT uContentSize = nIFileSize - SIGNATURELENGTH;
char* pcContent = new char[uContentSize + 1];
if (file->Read(pcContent, uContentSize) != uContentSize)
DEBUG_ONLY(theApp.QueueDebugLogLine(false, _T("PeerCache: Failed to read p2pinfo file content")));
pcContent[uContentSize] = '\0';
//----------- CHECKING .P2PINFO CONTENT
// NOTE: 'pcContent' gets destroyed with 'strtok' !
LPSTR pszLine = strtok(pcContent, "\r\n");
while (pszLine && !bContentCheckFailed)
{
strLine = pszLine;
int posSeperator = strLine.Find('=',1);
if ( posSeperator != -1 && strLine.GetLength() - posSeperator > 1)
{
CStringA strTopic = strLine.Left(posSeperator).Trim();
CStringA strContent = strLine.Mid(posSeperator+1).Trim();
//DEBUG_ONLY(theApp.QueueDebugLogLine(false, _T("PeerCache: Current line to be processed: %hs"),strLine);
///////***** CacheIP
if (strTopic == "CacheIP"){
adwCacheIPs.Add(inet_addr(strContent));
}
///////***** ClientIPRange
else if (strTopic == "ClientIPRange"){
astrIPRanges.Add(strContent);
}
///////***** ExpireDate
else if (strTopic == "ExpireDate"){
bool bDateCheckFailed = true;
if (strContent.GetLength() == 8){
uint32 nYear = atol(strContent.Mid(0,4));
uint32 nMonth = atol(strContent.Mid(4,2));
uint32 nDay = atol(strContent.Mid(6,2));
if (nYear <= 3000 && nMonth <= 12 && nDay <= 31){
CTime timeExpireDate(nYear, nMonth, nDay, 0, 0, 0);
if (timeExpireDate >= CTime::GetCurrentTime())
bDateCheckFailed = false; // check passed
}
}
if (bDateCheckFailed){
bContentCheckFailed = true;
DEBUG_ONLY(theApp.QueueDebugLogLine(false, _T("PeerCache: ExpireDate check failed. Expiring date: %hs"),strContent));
}
}
///////***** EnableED2K
else if (strTopic == "EnableED2K"){
if (atol(strContent) != 1){
bContentCheckFailed = true;
DEBUG_ONLY(theApp.QueueDebugLogLine(false, _T("PeerCache: EnableED2K check failed. Value: %hs"),strContent));
}
}
else{
DEBUG_ONLY(theApp.QueueDebugLogLine(false, _T("PeerCache: Unused content tag for validity check: %hs"),strLine));
}
}
pszLine = strtok(NULL, "\r\n");
}
// finish the CacheIP check
bool bIPRangeCheckFailed = true;
for (int i = 0; i != adwCacheIPs.GetCount(); i++){
if(adwCacheIPs[i] == m_dwPCIP){
bIPRangeCheckFailed = false;
break;
}
}
if (bIPRangeCheckFailed){
bContentCheckFailed = true;
DEBUG_ONLY(theApp.QueueDebugLogLine(false, _T("PeerCache: CacheIP check failed.")));
}
// finish the RangeChack
bool bIPCheckFailed = true;
for (int i = 0; i != astrIPRanges.GetCount(); i++){
CStringA strCurRange = astrIPRanges[i];
int posContentSeperator = strCurRange.Find('-',7);
if ( !(posContentSeperator == -1 || strCurRange.GetLength() - posContentSeperator <= 7) ){
uint32 dwIPRangeStart = inet_addr(strCurRange.Left(posContentSeperator).Trim());
uint32 dwIPRangeEnd = inet_addr(strCurRange.Mid(posContentSeperator+1).Trim());
if (dwIPRangeStart != INADDR_NONE || dwIPRangeEnd != INADDR_NONE){
if (ntohl(dwIPRangeStart) <= ntohl(m_dwMyIP) && ntohl(dwIPRangeEnd) >= ntohl(m_dwMyIP))
bIPCheckFailed = false; // check passed
}
}
}
if (bIPCheckFailed){
bContentCheckFailed = true;
DEBUG_ONLY(theApp.QueueDebugLogLine(false, _T("PeerCache: ClientIPRange check failed. my IP: %s"), ipstr(m_dwMyIP)));
}
//----------- CHECKING SPECIAL HEADERS CONTENT
char achBuffer[3072]; // 3KB should be enough for headers
DWORD nBufferSize = sizeof(achBuffer);
if( !bContentCheckFailed && HttpQueryInfo(*file, HTTP_QUERY_RAW_HEADERS_CRLF, achBuffer, &nBufferSize, NULL) ){
CStringA strHeaders = achBuffer;
int nHeaderPos = 0;
CStringA strCurHeader = strHeaders.Tokenize("\r\n",nHeaderPos);
while (!strCurHeader.IsEmpty())
{
int posSeperator = strCurHeader.Find(':',1);
if ( posSeperator != -1 && strCurHeader.GetLength() - posSeperator > 1)
{
CStringA strTopic = strCurHeader.Left(posSeperator).Trim();
CStringA strContent = strCurHeader.Mid(posSeperator+1).Trim();
DEBUG_ONLY(theApp.QueueDebugLogLine(false, _T("PeerCache: Current Header to be processed: %hs"),strCurHeader));
///////***** X-eMule-Require-Version
if (strTopic == "X-eMule-Require-Version"){
int curPos= 0;
CString strPCEncodedVersion(strContent);
CString strVersion = strPCEncodedVersion.Tokenize(_T(" "),curPos);
while (!strVersion.IsEmpty())
{
m_pOwner->AddAllowedVersion(CClientVersionInfo(strVersion));
strVersion = strPCEncodedVersion.Tokenize(_T(" "),curPos);
}
}
///////***** X-eMule-Reject-Version
else if (strTopic == "X-eMule-Reject-Version"){
int curPos= 0;
CString strPCEncodedVersion(strContent);
CString strVersion = strPCEncodedVersion.Tokenize(_T(" "),curPos);
while (!strVersion.IsEmpty())
{
m_pOwner->AddBannedVersion(CClientVersionInfo(strVersion));
strVersion = strPCEncodedVersion.Tokenize(_T(" "),curPos);
}
}
}
strCurHeader = strHeaders.Tokenize("\r\n",nHeaderPos);
}
///////***** Own version check
if (!m_pOwner->IsClientPCCompatible(CClientVersionInfo(VERSION_MJR, VERSION_MIN, VERSION_UPDATE, VERSION_BUILD, SO_EMULE))){
bContentCheckFailed = true;
DEBUG_ONLY(theApp.QueueDebugLogLine(false, _T("PeerCache: Current Version not allowed to use this PC-Server, please update")));
}
}
else if (!bContentCheckFailed)
DEBUG_ONLY(theApp.QueueDebugLogLine(false, _T("PeerCache Error: Failed to retrieve headers, Errornumber %s"),GetErrorMessage(GetLastError()) ));
//----------- CHECKING .P2PINFO SIGNATURE
bool bSignatureCheckResult = false;
if (!bContentCheckFailed){
uchar* pachCompleteFile = new uchar[nIFileSize];
file->SeekToBegin();
if (file->Read(pachCompleteFile, nIFileSize) != nIFileSize){
ASSERT( false );
bSignatureCheckResult = false;
}
else{
using namespace CryptoPP;
Integer e, m, n;
e = 3;
n.Decode(achVerify_Key, ARRSIZE(achVerify_Key));
uchar aucSignature[SIGNATURELENGTH];
for (int i = 0; i != SIGNATURELENGTH; i++)
aucSignature[(SIGNATURELENGTH-1)-i] = pachCompleteFile[(nIFileSize-SIGNATURELENGTH)+i];
m.Decode(aucSignature, SIGNATURELENGTH);
RSAFunction rsa;
rsa.SetPublicExponent(e);
rsa.SetModulus(n);
Integer result = rsa.ApplyFunction(m);
uchar aucResult[SIGNATURELENGTH];
if(result.Encode(aucResult, SIGNATURELENGTH)){
uchar aucHash1[16];
for (int i = 0; i != 16; i++)
aucHash1[i] = aucResult[(SIGNATURELENGTH-1)-i];
bSignatureCheckResult = md4cmp(MD5Sum(pachCompleteFile, nIFileSize-SIGNATURELENGTH).GetRawHash(), aucHash1) == 0;
}
}
delete[] pachCompleteFile;
if (!bSignatureCheckResult)
DEBUG_ONLY(theApp.QueueDebugLogLine(false, _T("PeerCache: Failed to verify PeerCache Server, not using it")));
}
delete[] pcContent;
file->Close();
delete file;
return (bSignatureCheckResult && !bContentCheckFailed );
}
return false;
}
BEGIN_MESSAGE_MAP(CPCValditeThread, CWinThread)
END_MESSAGE_MAP()
IMPLEMENT_DYNCREATE(CPCReverseDnsThread, CWinThread)
BOOL CPCReverseDnsThread::InitInstance()
{
ASSERT( m_hwndAsyncResult != NULL );
ASSERT( m_dwIP != 0 );
InitThreadLocale();
memset(_acDNSBuffer, 0, sizeof _acDNSBuffer);
CString strHostname = ReverseDnsLookup(m_dwIP);
UINT uBufLen = 0;
UINT uError = WSAEINVAL;
if (!strHostname.IsEmpty())
{
CStringA strHostnameA(strHostname);
uBufLen = sizeof(HOSTENT) // 'hostent' structure
+ sizeof(char*) // h_aliases list + NUL entry
+ sizeof(DWORD)*2 // h_addr_list + NUL entry
+ strHostnameA.GetLength() + 1;
if (uBufLen <= sizeof(_acDNSBuffer))
{
LPHOSTENT pHost = (LPHOSTENT)_acDNSBuffer;
char* p = (char*)(pHost + 1);
pHost->h_aliases = (char**)p;
pHost->h_aliases[0] = (char*)NULL;
p += sizeof(char*);
pHost->h_addrtype = AF_INET;
pHost->h_length = sizeof(DWORD);
pHost->h_addr_list = (char**)p;
pHost->h_addr_list[0] = (char*)m_dwIP;
pHost->h_addr_list[1] = (char*)NULL;
p += sizeof(char*)*2;
pHost->h_name = p;
strcpy(pHost->h_name, strHostnameA);
p += strHostnameA.GetLength() + 1;
ASSERT( p - _acDNSBuffer == uBufLen );
uError = 0;
}
else
uError = WSAENOBUFS;
VERIFY( PostMessage(m_hwndAsyncResult, WM_PEERCHACHE_RESPONSE, 0, WSAMAKEASYNCREPLY(uBufLen, uError)) );
}
else
{
in_addr IPHost;
// FIXME: Unable to resolve my own host - will always get the Windows Computer/Domainname. Dunno how to avoid this
// cheap walk arround below by using another IP
IPHost.s_addr = ntohl(ntohl(m_dwIP)+1);
if (WSAAsyncGetHostByAddr(theApp.emuledlg->m_hWnd, WM_PEERCHACHE_RESPONSE, (const char*) &IPHost, sizeof(struct in_addr), AF_INET, _acDNSBuffer, sizeof(_acDNSBuffer)) == 0){
if (thePrefs.GetVerbose())
DEBUG_ONLY(theApp.QueueDebugLogLine(false, _T("DNS Reverse Lookup for own IP failed")));
}
}
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -