1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278 | //
// This file is part of the aMule Project.
//
// Copyright (c) 2004-2011 Angel Vidal ( kry@amule.org )
// Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org )
// Copyright (c) 2002-2011 Merkur ( devs@emule-project.net / http://www.emule-project.net )
//
// Any parts of this program derived from the xMule, lMule or eMule project,
// or contributed by third-party developers are copyrighted by their
// respective authors.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
//
/*
SHA hashset basically exists of 1 Tree for all Parts (9.28MB) + n Trees
for all blocks (180KB) while n is the number of Parts.
This means it is NOT a complete hashtree, since the 9.28MB is a given level, in order
to be able to create a hashset format similar to the MD4 one.
If the number of elements for the next level are odd (for example 21 blocks to spread into 2 hashs)
the majority of elements will go into the left branch if the parent node was a left branch
and into the right branch if the parent node was a right branch. The first node is always
taken as a left branch.
Example tree:
FileSize: 19506000 Bytes = 18,6 MB
X(18,6 MB) MasterHash
/ \
X(18,55) \
/ \ \
X(9,28) X(9,28) X(0,05MB) PartHashs
/ \ / \ \
X(4,75) X(4,57) X(4,57) X(4,57) X(4,75)
[...............]
X(180KB) X(180KB) [...] X(140KB) | X(180KB) X(180KB) [...] BlockHashs
v
Border between first and second Part (9.28MB)
HashsIdentifier:
When sending hashes, they are sent with a 16bit identifier which specifies its position in the
tree (so StartPosition + HashDataSize would lead to the same hash)
The identifier basically describes the way from the top of the tree to the hash. a set bit (1)
means follow the left branch, a 0 means follow the right. The highest bit which is set is seen as the start-
position (since the first node is always seen as left).
Example
x 0000000000000001
/ \
x \ 0000000000000011
/ \ \
x _X_ x 0000000000000110
Version 2 of AICH also supports 32bit identifiers to support large files, check CAICHHashSet::CreatePartRecoveryData
*/
#ifndef __SHAHAHSET_H__
#define __SHAHAHSET_H__
#include <deque>
#include <set>
#include "Types.h"
#include "ClientRef.h"
#define HASHSIZE 20
#define KNOWN2_MET_FILENAME wxT("known2_64.met")
#define OLD_KNOWN2_MET_FILENAME wxT("known2.met")
#define KNOWN2_MET_VERSION 0x02
enum EAICHStatus {
AICH_ERROR = 0,
AICH_EMPTY,
AICH_UNTRUSTED,
AICH_TRUSTED,
AICH_VERIFIED,
AICH_HASHSETCOMPLETE
};
class CFileDataIO;
class CKnownFile;
class CMemFile;
class CPartFile;
class CUpDownClient;
/////////////////////////////////////////////////////////////////////////////////////////
///CAICHHash
class CAICHHash
{
private:
uint8_t m_abyBuffer[HASHSIZE];
public:
CAICHHash() { memset(m_abyBuffer, 0, HASHSIZE); }
CAICHHash(CFileDataIO* file) { Read(file); }<--- Class 'CAICHHash' has a constructor with 1 argument that is not explicit. [+]Class 'CAICHHash' has a constructor with 1 argument that is not explicit. Such, so called "Converting constructors", should in general be explicit for type safety reasons as that prevents unintended implicit conversions.
CAICHHash(uint8_t* data) { Read(data); }<--- Class 'CAICHHash' has a constructor with 1 argument that is not explicit. [+]Class 'CAICHHash' has a constructor with 1 argument that is not explicit. Such, so called "Converting constructors", should in general be explicit for type safety reasons as that prevents unintended implicit conversions.
CAICHHash(const CAICHHash& k1) { *this = k1; }
~CAICHHash() {}
CAICHHash& operator=(const CAICHHash& k1)
{
memcpy(m_abyBuffer, k1.m_abyBuffer, HASHSIZE);
return *this;
}
friend bool operator==(const CAICHHash& k1,const CAICHHash& k2)
{
return memcmp(k1.m_abyBuffer, k2.m_abyBuffer, HASHSIZE) == 0;
}
friend bool operator!=(const CAICHHash& k1,const CAICHHash& k2) { return !(k1 == k2); }
void Read(CFileDataIO* file);
void Write(CFileDataIO* file) const;
void Read(uint8_t* data) { memcpy(m_abyBuffer, data, HASHSIZE); }<--- Parameter 'data' can be declared as pointer to const
wxString GetString() const;
uint8_t* GetRawHash() { return m_abyBuffer; }
static uint32 GetHashSize() { return HASHSIZE;}
unsigned int DecodeBase32(const wxString &base32);
};
/////////////////////////////////////////////////////////////////////////////////////////
///CAICHHashAlgo
class CAICHHashAlgo
{
public:
virtual ~CAICHHashAlgo() {};
virtual void Reset() = 0;
virtual void Add(const void* pData, uint32 nLength) = 0;
virtual void Finish(CAICHHash& Hash) = 0;
virtual void GetHash(CAICHHash& Hash) = 0;
};
/////////////////////////////////////////////////////////////////////////////////////////
///CAICHHashTree
class CAICHHashTree
{
friend class CAICHHashSet;
private:
CAICHHash m_Hash;
uint64 m_nDataSize; // size of data which is covered by this hash
uint64 m_nBaseSize; // blocksize on which the lowest hash is based on
bool m_bIsLeftBranch; // left or right branch of the tree
bool m_bHashValid; // the hash is valid and not empty
CAICHHashTree* m_pLeftTree;
CAICHHashTree* m_pRightTree;
public:
CAICHHashTree(uint64 nDataSize, bool bLeftBranch, uint64 nBaseSize);
~CAICHHashTree();
const CAICHHash &GetHash() const { return m_Hash; }
uint64 GetNDataSize() const { return m_nDataSize; }
uint64 GetNBaseSize() const { return m_nBaseSize; }
bool GetIsLeftBranch() const { return m_bIsLeftBranch; }
bool GetHashValid() const { return m_bHashValid; }
void SetBlockHash(uint64 nSize, uint64 nStartPos, CAICHHashAlgo* pHashAlg);
bool ReCalculateHash(CAICHHashAlgo* hashalg, bool bDontReplace );
bool VerifyHashTree(CAICHHashAlgo* hashalg, bool bDeleteBadTrees);
CAICHHashTree* FindHash(uint64 nStartPos, uint64 nSize)
{
uint8 buffer = 0;
return FindHash(nStartPos, nSize, &buffer);
}
protected:
CAICHHashTree* FindHash(uint64 nStartPos, uint64 nSize, uint8* nLevel);
bool CreatePartRecoveryData(uint64 nStartPos, uint64 nSize,
CFileDataIO* fileDataOut, uint32 wHashIdent, bool b32BitIdent);
void WriteHash(CFileDataIO* fileDataOut, uint32 wHashIdent, bool b32BitIdent) const;
bool WriteLowestLevelHashs(CFileDataIO* fileDataOut,
uint32 wHashIdent, bool bNoIdent, bool b32BitIdent) const;
bool LoadLowestLevelHashs(CFileDataIO* fileInput);
bool SetHash(CFileDataIO* fileInput, uint32 wHashIdent, sint8 nLevel = (-1), bool bAllowOverwrite = true);
};
/////////////////////////////////////////////////////////////////////////////////////////
///CAICHUntrustedHashs
class CAICHUntrustedHash {
public:
CAICHUntrustedHash& operator=(const CAICHUntrustedHash& k1)
{
m_adwIpsSigning = k1.m_adwIpsSigning;
m_Hash = k1.m_Hash ;
return *this;
}
bool AddSigningIP(uint32 dwIP);
CAICHHash m_Hash;
std::set<uint32> m_adwIpsSigning;
};
/////////////////////////////////////////////////////////////////////////////////////////
///CAICHUntrustedHashs
class CAICHRequestedData {
public:
CAICHRequestedData()
{
m_nPart = 0;
m_pPartFile = NULL;
}
CAICHRequestedData& operator=(const CAICHRequestedData& k1)
{
m_nPart = k1.m_nPart;
m_pPartFile = k1.m_pPartFile;
m_pClient = k1.m_pClient;
return *this;
}
uint16 m_nPart;
CPartFile* m_pPartFile;
CClientRef m_pClient;
};
using namespace std;
typedef std::list<CAICHRequestedData> CAICHRequestedDataList;
/////////////////////////////////////////////////////////////////////////////////////////
///CAICHHashSet
class CAICHHashSet
{
private:
CKnownFile* m_pOwner;
EAICHStatus m_eStatus;
deque<CAICHUntrustedHash> m_aUntrustedHashs;
public:
static CAICHRequestedDataList m_liRequestedData;
CAICHHashTree m_pHashTree;
CAICHHashSet(CKnownFile* pOwner);<--- Class 'CAICHHashSet' has a constructor with 1 argument that is not explicit. [+]Class 'CAICHHashSet' has a constructor with 1 argument that is not explicit. Such, so called "Converting constructors", should in general be explicit for type safety reasons as that prevents unintended implicit conversions.
~CAICHHashSet(void);
bool CreatePartRecoveryData(uint64 nPartStartPos, CFileDataIO* fileDataOut, bool bDbgDontLoad = false);
bool ReadRecoveryData(uint64 nPartStartPos, CMemFile* fileDataIn);
bool ReCalculateHash(bool bDontReplace = false);
bool VerifyHashTree(bool bDeleteBadTrees);
void UntrustedHashReceived(const CAICHHash& Hash, uint32 dwFromIP);
bool IsPartDataAvailable(uint64 nPartStartPos);
void SetStatus(EAICHStatus bNewValue) { m_eStatus = bNewValue; }
EAICHStatus GetStatus() const { return m_eStatus; }
void FreeHashSet();
void SetFileSize(uint64 nSize);
CAICHHash& GetMasterHash() { return m_pHashTree.m_Hash; }
void SetMasterHash(const CAICHHash& Hash, EAICHStatus eNewStatus);
bool HasValidMasterHash() { return m_pHashTree.m_bHashValid; }
bool SaveHashSet();
bool LoadHashSet(); // only call directly when debugging
static CAICHHashAlgo* GetNewHashAlgo();
static void ClientAICHRequestFailed(CUpDownClient* pClient);
static void RemoveClientAICHRequest(const CUpDownClient* pClient);
static bool IsClientRequestPending(const CPartFile* pForFile, uint16 nPart);
static CAICHRequestedData GetAICHReqDetails(const CUpDownClient* pClient);
void DbgTest();
void SetOwner(CKnownFile* owner) { m_pOwner = owner; }
};
#endif //__SHAHAHSET_H__
// File_checked_for_headers
|