📄 knownfile.cpp
字号:
CTag aichtag(FT_AICH_HASH, m_pAICHHashSet->GetMasterHash().GetString());
aichtag.WriteTagToFile(file);
uTagCount++;
}
if (m_lastPublishTimeKadSrc){
CTag kadLastPubSrc(FT_KADLASTPUBLISHSRC, m_lastPublishTimeKadSrc);
kadLastPubSrc.WriteTagToFile(file);
uTagCount++;
}
if (m_uMetaDataVer > 0)
{
// Misc. Flags
// ------------------------------------------------------------------------------
// Bits 3-0: Meta data version
// 0 = Unknown
// 1 = we have created that meta data by examining the file contents.
// Bits 31-4: Reserved
ASSERT( m_uMetaDataVer <= 0x0F );
uint32 uFlags = m_uMetaDataVer & 0x0F;
CTag tagFlags(FT_FLAGS, uFlags);
tagFlags.WriteTagToFile(file);
uTagCount++;
}
//other tags
for (int j = 0; j < taglist.GetCount(); j++){
if (taglist[j]->IsStr() || taglist[j]->IsInt()){
taglist[j]->WriteTagToFile(file);
uTagCount++;
}
}
file->Seek(uTagCountFilePos, CFile::begin);
file->WriteUInt32(uTagCount);
file->Seek(0, CFile::end);
return true;
}
void CKnownFile::CreateHashFromInput(FILE* file,CFile* file2, int Length, uchar* Output, uchar* in_string, CAICHHashTree* pShaHashOut) const
{
ASSERT( Output != NULL || pShaHashOut != NULL);
// time critial
bool PaddingStarted = false;
uint32 Hash[4];
Hash[0] = 0x67452301;
Hash[1] = 0xEFCDAB89;
Hash[2] = 0x98BADCFE;
Hash[3] = 0x10325476;
CFile* data = NULL;
if (in_string)
data = new CMemFile(in_string,Length);
uint32 Required = Length;
uchar X[64*128];
uint32 posCurrentEMBlock = 0;
uint32 nIACHPos = 0;
CAICHHashAlgo* pHashAlg = m_pAICHHashSet->GetNewHashAlgo();
while (Required >= 64){
uint32 len = Required / 64;
if (len > sizeof(X)/(64 * sizeof(X[0])))
len = sizeof(X)/(64 * sizeof(X[0]));
if (in_string)
data->Read(&X,len*64);
else if (file)
fread(&X,len*64,1,file);
else if (file2)
file2->Read(&X,len*64);
// SHA hash needs 180KB blocks
if (pShaHashOut != NULL){
if (nIACHPos + len*64 >= EMBLOCKSIZE){
uint32 nToComplete = EMBLOCKSIZE - nIACHPos;
pHashAlg->Add(X, nToComplete);
ASSERT( nIACHPos + nToComplete == EMBLOCKSIZE );
pShaHashOut->SetBlockHash(EMBLOCKSIZE, posCurrentEMBlock, pHashAlg);
posCurrentEMBlock += EMBLOCKSIZE;
pHashAlg->Reset();
pHashAlg->Add(X+nToComplete,(len*64) - nToComplete);
nIACHPos = (len*64) - nToComplete;
}
else{
pHashAlg->Add(X, len*64);
nIACHPos += len*64;
}
}
if (Output != NULL){
for (uint32 i = 0; i < len; i++)
{
MD4Transform(Hash, (uint32*)(X + i*64));
}
}
Required -= len*64;
}
// bytes to read
Required = Length % 64;
if (Required != 0){
if (in_string)
data->Read(&X,Required);
else if (file)
fread(&X,Required,1,file);
else if (file2)
file2->Read(&X,Required);
if (pShaHashOut != NULL){
if (nIACHPos + Required >= EMBLOCKSIZE){
uint32 nToComplete = EMBLOCKSIZE - nIACHPos;
pHashAlg->Add(X, nToComplete);
ASSERT( nIACHPos + nToComplete == EMBLOCKSIZE );
pShaHashOut->SetBlockHash(EMBLOCKSIZE, posCurrentEMBlock, pHashAlg);
posCurrentEMBlock += EMBLOCKSIZE;
pHashAlg->Reset();
pHashAlg->Add(X+nToComplete, Required - nToComplete);
nIACHPos = Required - nToComplete;
}
else{
pHashAlg->Add(X, Required);
nIACHPos += Required;
}
}
}
if (pShaHashOut != NULL){
if(nIACHPos > 0){
pShaHashOut->SetBlockHash(nIACHPos, posCurrentEMBlock, pHashAlg);
posCurrentEMBlock += nIACHPos;
}
ASSERT( posCurrentEMBlock == Length );
VERIFY( pShaHashOut->ReCalculateHash(pHashAlg, false) );
}
if (Output != NULL){
// in byte scale 512 = 64, 448 = 56
if (Required >= 56){
X[Required] = 0x80;
PaddingStarted = TRUE;
memset(&X[Required + 1], 0, 63 - Required);
MD4Transform(Hash, (uint32*)X);
Required = 0;
}
if (!PaddingStarted)
X[Required++] = 0x80;
memset(&X[Required], 0, 64 - Required);
// add size (convert to bits)
uint32 Length2 = Length >> 29;
Length <<= 3;
memcpy(&X[56], &Length, 4);
memcpy(&X[60], &Length2, 4);
MD4Transform(Hash, (uint32*)X);
md4cpy(Output, Hash);
}
delete pHashAlg;
if (data)
delete data;
}
uchar* CKnownFile::GetPartHash(uint16 part) const {
if (part >= hashlist.GetCount())
return 0;
return hashlist[part];
}
static void MD4Transform(uint32 Hash[4], uint32 x[16])
{
uint32 a = Hash[0];
uint32 b = Hash[1];
uint32 c = Hash[2];
uint32 d = Hash[3];
/* Round 1 */
MD4_FF(a, b, c, d, x[ 0], S11); // 01
MD4_FF(d, a, b, c, x[ 1], S12); // 02
MD4_FF(c, d, a, b, x[ 2], S13); // 03
MD4_FF(b, c, d, a, x[ 3], S14); // 04
MD4_FF(a, b, c, d, x[ 4], S11); // 05
MD4_FF(d, a, b, c, x[ 5], S12); // 06
MD4_FF(c, d, a, b, x[ 6], S13); // 07
MD4_FF(b, c, d, a, x[ 7], S14); // 08
MD4_FF(a, b, c, d, x[ 8], S11); // 09
MD4_FF(d, a, b, c, x[ 9], S12); // 10
MD4_FF(c, d, a, b, x[10], S13); // 11
MD4_FF(b, c, d, a, x[11], S14); // 12
MD4_FF(a, b, c, d, x[12], S11); // 13
MD4_FF(d, a, b, c, x[13], S12); // 14
MD4_FF(c, d, a, b, x[14], S13); // 15
MD4_FF(b, c, d, a, x[15], S14); // 16
/* Round 2 */
MD4_GG(a, b, c, d, x[ 0], S21); // 17
MD4_GG(d, a, b, c, x[ 4], S22); // 18
MD4_GG(c, d, a, b, x[ 8], S23); // 19
MD4_GG(b, c, d, a, x[12], S24); // 20
MD4_GG(a, b, c, d, x[ 1], S21); // 21
MD4_GG(d, a, b, c, x[ 5], S22); // 22
MD4_GG(c, d, a, b, x[ 9], S23); // 23
MD4_GG(b, c, d, a, x[13], S24); // 24
MD4_GG(a, b, c, d, x[ 2], S21); // 25
MD4_GG(d, a, b, c, x[ 6], S22); // 26
MD4_GG(c, d, a, b, x[10], S23); // 27
MD4_GG(b, c, d, a, x[14], S24); // 28
MD4_GG(a, b, c, d, x[ 3], S21); // 29
MD4_GG(d, a, b, c, x[ 7], S22); // 30
MD4_GG(c, d, a, b, x[11], S23); // 31
MD4_GG(b, c, d, a, x[15], S24); // 32
/* Round 3 */
MD4_HH(a, b, c, d, x[ 0], S31); // 33
MD4_HH(d, a, b, c, x[ 8], S32); // 34
MD4_HH(c, d, a, b, x[ 4], S33); // 35
MD4_HH(b, c, d, a, x[12], S34); // 36
MD4_HH(a, b, c, d, x[ 2], S31); // 37
MD4_HH(d, a, b, c, x[10], S32); // 38
MD4_HH(c, d, a, b, x[ 6], S33); // 39
MD4_HH(b, c, d, a, x[14], S34); // 40
MD4_HH(a, b, c, d, x[ 1], S31); // 41
MD4_HH(d, a, b, c, x[ 9], S32); // 42
MD4_HH(c, d, a, b, x[ 5], S33); // 43
MD4_HH(b, c, d, a, x[13], S34); // 44
MD4_HH(a, b, c, d, x[ 3], S31); // 45
MD4_HH(d, a, b, c, x[11], S32); // 46
MD4_HH(c, d, a, b, x[ 7], S33); // 47
MD4_HH(b, c, d, a, x[15], S34); // 48
Hash[0] += a;
Hash[1] += b;
Hash[2] += c;
Hash[3] += d;
}
void CAbstractFile::SetFileName(LPCTSTR pszFileName, bool bReplaceInvalidFileSystemChars, bool bAutoSetFileType)
{
m_strFileName = pszFileName;
if (bReplaceInvalidFileSystemChars){
m_strFileName.Replace(_T('/'), _T('-'));
m_strFileName.Replace(_T('>'), _T('-'));
m_strFileName.Replace(_T('<'), _T('-'));
m_strFileName.Replace(_T('*'), _T('-'));
m_strFileName.Replace(_T(':'), _T('-'));
m_strFileName.Replace(_T('?'), _T('-'));
m_strFileName.Replace(_T('\"'), _T('-'));
m_strFileName.Replace(_T('\\'), _T('-'));
m_strFileName.Replace(_T('|'), _T('-'));
}
if (bAutoSetFileType)
SetFileType(GetFileTypeByName(m_strFileName));
}
void CAbstractFile::SetFileType(LPCTSTR pszFileType)
{
m_strFileType = pszFileType;
}
CString CAbstractFile::GetFileTypeDisplayStr() const
{
CString strFileTypeDisplayStr(GetFileTypeDisplayStrFromED2KFileType(GetFileType()));
if (strFileTypeDisplayStr.IsEmpty())
strFileTypeDisplayStr = GetFileType();
return strFileTypeDisplayStr;
}
void CAbstractFile::SetFileHash(const uchar* pucFileHash)
{
md4cpy(m_abyFileHash, pucFileHash);
}
bool CAbstractFile::HasNullHash() const
{
return isnulmd4(m_abyFileHash);
}
uint32 CAbstractFile::GetIntTagValue(uint8 tagname) const
{
for (int i = 0; i < taglist.GetSize(); i++){
const CTag* pTag = taglist[i];
if (pTag->GetNameID()==tagname && pTag->IsInt())
return pTag->GetInt();
}
return NULL;
}
bool CAbstractFile::GetIntTagValue(uint8 tagname, uint32& ruValue) const
{
for (int i = 0; i < taglist.GetSize(); i++){
const CTag* pTag = taglist[i];
if (pTag->GetNameID()==tagname && pTag->IsInt()){
ruValue = pTag->GetInt();
return true;
}
}
return false;
}
uint32 CAbstractFile::GetIntTagValue(LPCSTR tagname) const
{
for (int i = 0; i < taglist.GetSize(); i++){
const CTag* pTag = taglist[i];
if (pTag->GetNameID()==0 && pTag->IsInt() && CmpED2KTagName(pTag->GetName(), tagname)==0)
return pTag->GetInt();
}
return NULL;
}
const CString& CAbstractFile::GetStrTagValue(uint8 tagname) const
{
for (int i = 0; i < taglist.GetSize(); i++){
const CTag* pTag = taglist[i];
if (pTag->GetNameID()==tagname && pTag->IsStr())
return pTag->GetStr();
}
static const CString _strEmpty;
return _strEmpty;
}
const CString& CAbstractFile::GetStrTagValue(LPCSTR tagname) const
{
for (int i = 0; i < taglist.GetSize(); i++){
const CTag* pTag = taglist[i];
if (pTag->GetNameID()==0 && pTag->IsStr() && CmpED2KTagName(pTag->GetName(), tagname)==0)
return pTag->GetStr();
}
static const CString _strEmpty;
return _strEmpty;
}
CTag* CAbstractFile::GetTag(uint8 tagname, uint8 tagtype) const
{
for (int i = 0; i < taglist.GetSize(); i++){
CTag* pTag = taglist[i];
if (pTag->GetNameID()==tagname && pTag->GetType()==tagtype)
return pTag;
}
return NULL;
}
CTag* CAbstractFile::GetTag(LPCSTR tagname, uint8 tagtype) const
{
for (int i = 0; i < taglist.GetSize(); i++){
CTag* pTag = taglist[i];
if (pTag->GetNameID()==0 && pTag->GetType()==tagtype && CmpED2KTagName(pTag->GetName(), tagname)==0)
return pTag;
}
return NULL;
}
CTag* CAbstractFile::GetTag(uint8 tagname) const
{
for (int i = 0; i < taglist.GetSize(); i++){
CTag* pTag = taglist[i];
if (pTag->GetNameID()==tagname)
return pTag;
}
return NULL;
}
CTag* CAbstractFile::GetTag(LPCSTR tagname) const
{
for (int i = 0; i < taglist.GetSize(); i++){
CTag* pTag = taglist[i];
if (pTag->GetNameID()==0 && CmpED2KTagName(pTag->GetName(), tagname)==0)
return pTag;
}
return NULL;
}
void CAbstractFile::AddTagUnique(CTag* pTag)
{
for (int i = 0; i < taglist.GetSize(); i++){
const CTag* pCurTag = taglist[i];
if ( ( (pCurTag->GetNameID()!=0 && pCurTag->GetNameID()==pTag->GetNameID())
|| (pCurTag->GetName()!=NULL && pTag->GetName()!=NULL && CmpED2KTagName(pCurTag->GetName(), pTag->GetName())==0)
)
&& pCurTag->GetType() == pTag->GetType()){
delete pCurTag;
taglist.SetAt(i, pTag);
return;
}
}
taglist.Add(pTag);
}
Packet* CKnownFile::CreateSrcInfoPacket(CUpDownClient* forClient) const
{
if(m_ClientUploadList.IsEmpty())
return NULL;
CSafeMemFile data(1024);
uint16 nCount = 0;
data.WriteHash16(forClient->GetUploadFileID());
data.WriteUInt16(nCount);
uint32 cDbgNoSrc = 0;
for( POSITION pos = m_ClientUploadList.GetHeadPosition();pos != 0;)
{
const CUpDownClient *cur_src = m_ClientUploadList.GetNext(pos);
if(cur_src->HasLowID() || cur_src == forClient || !(cur_src->GetUploadState() == US_UPLOADING || cur_src->GetUploadState() == US_ONUPLOADQUEUE))
continue;
if (!cur_src->IsEd2kClient())
continue;
bool bNeeded = false;
uint8* rcvstatus = forClient->GetUpPartStatus();
if( rcvstatus )
{
uint8* srcstatus = cur_src->GetUpPartStatus();
if( srcstatus )
{
if( cur_src->GetUpPartCount() == forClient->GetUpPartCount() )
{
for (int x = 0; x < GetPartCount(); x++ )
{
if( srcstatus[x] && !rcvstatus[x] )
{
// We know the recieving client needs a chunk from this client.
bNeeded = true;
break;
}
}
}
else
{
// should never happen
if (thePrefs.GetVerbose())
DEBUG_ONLY(AddDebugLogLine(false,_T("*** %hs - found source (%s) with wrong partcount (%u) attached to file \"%s\" (partcount=%u)"), __FUNCTION__, cur_src->DbgGetClientInfo(), cur_src->GetUpPartCount(), GetFileName(), GetPartCount()));
}
}
else
{
cDbgNoSrc++;
// This client doesn't support upload chunk status. So just send it and hope for the best.
bNeeded = true;
}
}
else
{
TRACE(_T("CKnownFile::CreateSrcInfoPacket, requesting client has no chunk status - %s"), forClient->DbgGetClientInfo());
// remote client does not support upload chunk status, search sources which have at least one complete part
// we could even sort the list of sources by available chunks to return as much sources as possible which
// have the most available chunks. but this could be a noticeable performance problem.
uint8* srcstatus = cur_src->GetUpPartStatus();
if( srcstatus )
{
for (int x = 0; x < GetPartCount(); x++ )
{
if( srcstatus[x] )
{
// this client has at least one chunk
bNeeded = true;
break;
}
}
}
else
{
// This client doesn't support upload chunk status. So just send it and hope for the best.
bNeeded = true;
}
}
if( bNeeded )
{
nCount++;
uint32 dwID;
if(forClient->GetSourceExchangeVersion() > 2)
dwID = cur_src->GetUserIDHybrid();
else
dwID = cur_src->GetIP();
data.WriteUInt32(dwID);
data.WriteUInt16(cur_src->GetUserPort());
data.WriteUInt32(cur_src->GetServerIP());
data.WriteUInt16(cur_src->GetServerPort());
if (forClient->GetSourceExchangeVersion() > 1)
data.WriteHash16(cur_src->GetUserHash());
if (nCount > 500)
break;
}
}
TRACE(_T("CKnownFile::CreateSrcInfoPacket: Out of %u clients, %u had no valid chunk status\n\r"),m_ClientUploadList.GetCount(), cDbgNoSrc);
if (!nCount)
return 0;
data.Seek(16,0);
data.WriteUInt16(nCount);
Packet* result = new Packet(&data, OP_EMULEPROT);
result->opcode = OP_ANSWERSOURCES;
// 16+2+501*(4+2+4+2+16) = 14046 bytes max.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -