📄 shahashset.cpp
字号:
return false;
}
if ( !m_pHashTree.m_bHashValid || m_pHashTree.m_nDataSize != m_pOwner->GetFileSize() || m_pHashTree.m_nDataSize == 0){
ASSERT( false );
return false;
}
CString fullpath=thePrefs.GetConfigDir();
fullpath.Append(KNOWN2_MET_FILENAME);
CSafeFile file;
CFileException fexp;
if (!file.Open(fullpath,CFile::modeCreate|CFile::modeRead|CFile::modeNoTruncate|CFile::osSequentialScan|CFile::typeBinary|CFile::shareDenyNone, &fexp)){
if (fexp.m_cause != CFileException::fileNotFound){
CString strError(_T("Failed to load ") KNOWN2_MET_FILENAME _T(" file"));
TCHAR szError[MAX_CFEXP_ERRORMSG];
if (fexp.GetErrorMessage(szError, ARRSIZE(szError))){
strError += _T(" - ");
strError += szError;
}
theApp.QueueLogLine(true, _T("%s"), strError);
}
return false;
}
try {
//setvbuf(file.m_pStream, NULL, _IOFBF, 16384);
CAICHHash CurrentHash;
uint32 nExistingSize = file.GetLength();
uint16 nHashCount;
while (file.GetPosition() < nExistingSize){
CurrentHash.Read(&file);
if (m_pHashTree.m_Hash == CurrentHash){
// found Hashset
uint32 nExpectedCount = (PARTSIZE/EMBLOCKSIZE + ((PARTSIZE % EMBLOCKSIZE != 0)? 1 : 0)) * (m_pHashTree.m_nDataSize/PARTSIZE);
if (m_pHashTree.m_nDataSize % PARTSIZE != 0)
nExpectedCount += (m_pHashTree.m_nDataSize % PARTSIZE)/EMBLOCKSIZE + (((m_pHashTree.m_nDataSize % PARTSIZE) % EMBLOCKSIZE != 0)? 1 : 0);
nHashCount = file.ReadUInt16();
if (nHashCount != nExpectedCount){
theApp.QueueDebugLogLine(true, _T("Failed to load HashSet: Available Hashs and expected hashcount differ!"));
return false;
}
uint32 dbgPos = file.GetPosition();
if (!m_pHashTree.LoadLowestLevelHashs(&file)){
theApp.QueueDebugLogLine(true, _T("Failed to load HashSet: LoadLowestLevelHashs failed!"));
return false;
}
uint32 dbgHashRead = (file.GetPosition()-dbgPos)/HASHSIZE;
if (!ReCalculateHash(false)){
theApp.QueueDebugLogLine(true, _T("Failed to load HashSet: Calculating loaded hashs failed!"));
return false;
}
if (CurrentHash != m_pHashTree.m_Hash){
theApp.QueueDebugLogLine(true, _T("Failed to load HashSet: Calculated Masterhash differs from given Masterhash - hashset corrupt!"));
return false;
}
return true;
}
nHashCount = file.ReadUInt16();
if (file.GetPosition() + nHashCount*HASHSIZE > nExistingSize){
AfxThrowFileException(CFileException::endOfFile, 0, file.GetFileName());
}
// skip the rest of this hashset
file.Seek(nHashCount*HASHSIZE, CFile::current);
}
theApp.QueueDebugLogLine(true, _T("Failed to load HashSet: HashSet not found!"));
}
catch(CFileException* error){
if (error->m_cause == CFileException::endOfFile)
theApp.QueueLogLine(true,GetResString(IDS_ERR_SERVERMET_BAD));
else{
TCHAR buffer[MAX_CFEXP_ERRORMSG];
error->GetErrorMessage(buffer, ARRSIZE(buffer));
theApp.QueueLogLine(true,GetResString(IDS_ERR_SERVERMET_UNKNOWN),buffer);
}
error->Delete();
}
return false;
}
// delete the hashset except the masterhash (we dont keep aich hashsets in memory to save ressources)
void CAICHHashSet::FreeHashSet(){
if (m_pHashTree.m_pLeftTree){
delete m_pHashTree.m_pLeftTree;
m_pHashTree.m_pLeftTree = NULL;
}
if (m_pHashTree.m_pRightTree){
delete m_pHashTree.m_pRightTree;
m_pHashTree.m_pRightTree = NULL;
}
}
void CAICHHashSet::SetMasterHash(const CAICHHash& Hash, EAICHStatus eNewStatus){
m_pHashTree.m_Hash = Hash;
m_pHashTree.m_bHashValid = true;
SetStatus(eNewStatus);
}
CAICHHashAlgo* CAICHHashSet::GetNewHashAlgo(){
return new CSHA();
}
bool CAICHHashSet::ReCalculateHash(bool bDontReplace){
CAICHHashAlgo* hashalg = GetNewHashAlgo();
bool bResult = m_pHashTree.ReCalculateHash(hashalg, bDontReplace);
delete hashalg;
return bResult;
}
bool CAICHHashSet::VerifyHashTree(bool bDeleteBadTrees){
CAICHHashAlgo* hashalg = GetNewHashAlgo();
bool bResult = m_pHashTree.VerifyHashTree(hashalg, bDeleteBadTrees);
delete hashalg;
return bResult;
}
void CAICHHashSet::SetFileSize(uint32 nSize){
m_pHashTree.m_nDataSize = nSize;
m_pHashTree.m_nBaseSize = (nSize <= PARTSIZE) ? EMBLOCKSIZE : PARTSIZE;
}
void CAICHHashSet::UntrustedHashReceived(const CAICHHash& Hash, uint32 dwFromIP){
switch(GetStatus()){
case AICH_EMPTY:
case AICH_UNTRUSTED:
case AICH_TRUSTED:
break;
default:
return;
}
bool bFound = false;
bool bAdded = false;
for (int i = 0; i < m_aUntrustedHashs.GetCount(); i++){
if (m_aUntrustedHashs[i].m_Hash == Hash){
bAdded = m_aUntrustedHashs[i].AddSigningIP(dwFromIP);
bFound = true;
break;
}
}
if (!bFound){
bAdded = true;
CAICHUntrustedHash uhToAdd;
uhToAdd.m_Hash = Hash;
uhToAdd.AddSigningIP(dwFromIP);
m_aUntrustedHashs.Add(uhToAdd);
}
uint32 nSigningIPsTotal = 0; // unique clients who send us a hash
sint32 nMostTrustedPos = (-1); // the hash which most clients send us
uint32 nMostTrustedIPs = 0;
for (uint32 i = 0; i < (uint32)m_aUntrustedHashs.GetCount(); i++){
nSigningIPsTotal += m_aUntrustedHashs[i].m_adwIpsSigning.GetCount();
if ((uint32)m_aUntrustedHashs[i].m_adwIpsSigning.GetCount() > nMostTrustedIPs){
nMostTrustedIPs = m_aUntrustedHashs[i].m_adwIpsSigning.GetCount();
nMostTrustedPos = i;
}
}
if (nMostTrustedPos == (-1) || nSigningIPsTotal == 0){
ASSERT( false );
return;
}
// the check if we trust any hash
if ( thePrefs.IsTrustingEveryHash() ||
(nMostTrustedIPs >= MINUNIQUEIPS_TOTRUST && (100 * nMostTrustedIPs)/nSigningIPsTotal >= MINPERCENTAGE_TOTRUST)){
//trusted
//theApp.QueueDebugLogLine(false, _T("AICH Hash received: %s (%sadded), We have now %u hash from %u unique IPs. We trust the Hash %s from %u clients (%u%%). Added IP:%s, file: %s")
//, Hash.GetString(), bAdded? _T(""):_T("not "), m_aUntrustedHashs.GetCount(), nSigningIPsTotal, m_aUntrustedHashs[nMostTrustedPos].m_Hash.GetString()
//, nMostTrustedIPs, (100 * nMostTrustedIPs)/nSigningIPsTotal, ipstr(dwFromIP & 0x00F0FFFF), m_pOwner->GetFileName());
SetStatus(AICH_TRUSTED);
if (!HasValidMasterHash() || GetMasterHash() != m_aUntrustedHashs[nMostTrustedPos].m_Hash){
SetMasterHash(m_aUntrustedHashs[nMostTrustedPos].m_Hash, AICH_TRUSTED);
FreeHashSet();
}
}
else{
// untrusted
//theApp.QueueDebugLogLine(false, _T("AICH Hash received: %s (%sadded), We have now %u hash from %u unique IPs. Best Hash (%s) is from %u clients (%u%%) - but we dont trust it yet. Added IP:%s, file: %s")
// , Hash.GetString(), bAdded? _T(""):_T("not "), m_aUntrustedHashs.GetCount(), nSigningIPsTotal, m_aUntrustedHashs[nMostTrustedPos].m_Hash.GetString()
// , nMostTrustedIPs, (100 * nMostTrustedIPs)/nSigningIPsTotal, ipstr(dwFromIP & 0x00F0FFFF), m_pOwner->GetFileName());
SetStatus(AICH_UNTRUSTED);
if (!HasValidMasterHash() || GetMasterHash() != m_aUntrustedHashs[nMostTrustedPos].m_Hash){
SetMasterHash(m_aUntrustedHashs[nMostTrustedPos].m_Hash, AICH_UNTRUSTED);
FreeHashSet();
}
}
}
void CAICHHashSet::ClientAICHRequestFailed(CUpDownClient* pClient){
pClient->SetReqFileAICHHash(NULL);
CAICHRequestedData data = GetAICHReqDetails(pClient);
RemoveClientAICHRequest(pClient);
if (data.m_pClient != pClient)
return;
if(theApp.downloadqueue->IsPartFile(data.m_pPartFile)){
theApp.QueueDebugLogLine(false, _T("AICH Request failed, Trying to ask another client (file %s, Part: %u, Client%s)"), data.m_pPartFile->GetFileName(), data.m_nPart, pClient->DbgGetClientInfo());
data.m_pPartFile->RequestAICHRecovery(data.m_nPart);
}
}
void CAICHHashSet::RemoveClientAICHRequest(const CUpDownClient* pClient){
for (POSITION pos = m_liRequestedData.GetHeadPosition();pos != 0; m_liRequestedData.GetNext(pos))
{
if (m_liRequestedData.GetAt(pos).m_pClient == pClient){
m_liRequestedData.RemoveAt(pos);
return;
}
}
ASSERT( false );
}
bool CAICHHashSet::IsClientRequestPending(const CPartFile* pForFile, uint16 nPart){
for (POSITION pos = m_liRequestedData.GetHeadPosition();pos != 0; m_liRequestedData.GetNext(pos))
{
if (m_liRequestedData.GetAt(pos).m_pPartFile == pForFile && m_liRequestedData.GetAt(pos).m_nPart == nPart){
return true;
}
}
return false;
}
CAICHRequestedData CAICHHashSet::GetAICHReqDetails(const CUpDownClient* pClient){
for (POSITION pos = m_liRequestedData.GetHeadPosition();pos != 0; m_liRequestedData.GetNext(pos))
{
if (m_liRequestedData.GetAt(pos).m_pClient == pClient){
return m_liRequestedData.GetAt(pos);
}
}
ASSERT( false );
CAICHRequestedData empty;
return empty;
}
bool CAICHHashSet::IsPartDataAvailable(uint32 nPartStartPos){
if (!(m_eStatus == AICH_VERIFIED || m_eStatus == AICH_TRUSTED || m_eStatus == AICH_HASHSETCOMPLETE) ){
ASSERT( false );
return false;
}
uint32 nPartSize = min(PARTSIZE, m_pOwner->GetFileSize()-nPartStartPos);
for (uint32 nPartPos = 0; nPartPos < nPartSize; nPartPos += EMBLOCKSIZE){
CAICHHashTree* phtToCheck = m_pHashTree.FindHash(nPartStartPos+nPartPos, min(EMBLOCKSIZE, nPartSize-nPartPos));
if (phtToCheck == NULL || !phtToCheck->m_bHashValid){
return false;
}
}
return true;
}
void CAICHHashSet::DbgTest(){
#ifdef _DEBUG
//define TESTSIZE 4294567295
uint8 maxLevel = 0;
uint32 cHash = 1;
uint8 curLevel = 0;
uint32 cParts = 0;
maxLevel = 0;
/* CAICHHashTree* pTest = new CAICHHashTree(TESTSIZE, true, 9728000);
for (uint64 i = 0; i+9728000 < TESTSIZE; i += 9728000){
CAICHHashTree* pTest2 = new CAICHHashTree(9728000, true, EMBLOCKSIZE);
pTest->ReplaceHashTree(i, 9728000, &pTest2);
cParts++;
}
CAICHHashTree* pTest2 = new CAICHHashTree(TESTSIZE-i, true, EMBLOCKSIZE);
pTest->ReplaceHashTree(i, (TESTSIZE-i), &pTest2);
cParts++;
*/
#define TESTSIZE m_pHashTree.m_nDataSize
if (m_pHashTree.m_nDataSize <= EMBLOCKSIZE)
return;
CAICHHashSet TestHashSet(m_pOwner);
TestHashSet.SetFileSize(m_pOwner->GetFileSize());
TestHashSet.SetMasterHash(GetMasterHash(), AICH_VERIFIED);
CSafeMemFile file;
for (uint64 i = 0; i+9728000 < TESTSIZE; i += 9728000){
VERIFY( CreatePartRecoveryData(i, &file) );
/*uint32 nRandomCorruption = (rand() * rand()) % (file.GetLength()-4);
file.Seek(nRandomCorruption, CFile::begin);
file.Write(&nRandomCorruption, 4);*/
file.SeekToBegin();
VERIFY( TestHashSet.ReadRecoveryData(i, &file) );
file.SeekToBegin();
TestHashSet.FreeHashSet();
for (uint32 j = 0; j+EMBLOCKSIZE < 9728000; j += EMBLOCKSIZE){
VERIFY( m_pHashTree.FindHash(i+j, EMBLOCKSIZE, &curLevel) );
//TRACE(_T("%u - %s\r\n"), cHash, m_pHashTree.FindHash(i+j, EMBLOCKSIZE, &curLevel)->m_Hash.GetString());
maxLevel = max(curLevel, maxLevel);
curLevel = 0;
cHash++;
}
VERIFY( m_pHashTree.FindHash(i+j, 9728000-j, &curLevel) );
//TRACE(_T("%u - %s\r\n"), cHash, m_pHashTree.FindHash(i+j, 9728000-j, &curLevel)->m_Hash.GetString());
maxLevel = max(curLevel, maxLevel);
curLevel = 0;
cHash++;
}
VERIFY( CreatePartRecoveryData(i, &file) );
file.SeekToBegin();
VERIFY( TestHashSet.ReadRecoveryData(i, &file) );
file.SeekToBegin();
TestHashSet.FreeHashSet();
for (uint64 j = 0; j+EMBLOCKSIZE < TESTSIZE-i; j += EMBLOCKSIZE){
VERIFY( m_pHashTree.FindHash(i+j, EMBLOCKSIZE, &curLevel) );
//TRACE(_T("%u - %s\r\n"), cHash,m_pHashTree.FindHash(i+j, EMBLOCKSIZE, &curLevel)->m_Hash.GetString());
maxLevel = max(curLevel, maxLevel);
curLevel = 0;
cHash++;
}
//VERIFY( m_pHashTree.FindHash(i+j, (TESTSIZE-i)-j, &curLevel) );
TRACE(_T("%u - %s\r\n"), cHash,m_pHashTree.FindHash(i+j, (TESTSIZE-i)-j, &curLevel)->m_Hash.GetString());
maxLevel = max(curLevel, maxLevel);
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -