1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2008-2011 Dévai Tamás ( gonosztopi@amule.org )
5 // Copyright (c) 2004-2011 Angel Vidal ( kry@amule.org )
6 // Copyright (c) 2004-2011 aMule Team ( admin@amule.org / http://www.amule.org )
7 // Copyright (c) 2003-2011 Barry Dunne (http://www.emule-project.net)
8 //
9 // Any parts of this program derived from the xMule, lMule or eMule project,
10 // or contributed by third-party developers are copyrighted by their
11 // respective authors.
12 //
13 // This program is free software; you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation; either version 2 of the License, or
16 // (at your option) any later version.
17 //
18 // This program is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU General Public License for more details.
22 //
23 // You should have received a copy of the GNU General Public License
24 // along with this program; if not, write to the Free Software
25 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 //
27
28
29 // Note To Mods //
30 /*
31 Please do not change anything here and release it..
32 There is going to be a new forum created just for the Kademlia side of the client..
33 If you feel there is an error or a way to improve something, please
34 post it in the forum first and let us look at it.. If it is a real improvement,
35 it will be added to the offical client.. Changing something without knowing
36 what all it does can cause great harm to the network if released in mass form..
37 Any mod that changes anything within the Kademlia side will not be allowed to advertise
38 there client on the eMule forum..
CKadUDPKey(uint32_t key,uint32_t ip)39 */
40
41 #include "UInt128.h"
42
43 #include "../../ArchSpecific.h"
44 #include <common/Format.h> // Needed for CFormat
45
46
47 ////////////////////////////////////////
48 using namespace Kademlia;
49 ////////////////////////////////////////
50
51 CUInt128::CUInt128(const CUInt128 &value, unsigned numBits)
52 {
53 // Copy the whole uint32s
54 unsigned numULONGs = numBits / 32;
55 for (unsigned i = 0; i < numULONGs; i++) {
56 Set32BitChunk(i, value.Get32BitChunk(i));
57 }
58
59 // Copy the remaining bits
60 for (unsigned i = numULONGs * 32; i < numBits; i++) {
61 SetBitNumber(i, value.GetBitNumber(i));
62 }
63
64 // Fill the remaining bits of the current 32-bit chunk with random bits
65 // (Not seeding based on time to allow multiple different ones to be created in quick succession)
66 numULONGs = (numBits + 31) / 32;
67 for (unsigned i = numBits; i < numULONGs * 32; i++) {
68 SetBitNumber(i, rand() % 2);
69 }
70
71 // Pad with random bytes
72 for (unsigned i = numULONGs; i < 3; i++) {
73 Set32BitChunk(i, rand());
74 }
75 }
76
77 wxString CUInt128::ToHexString() const
78 {
79 wxString str;
80
81 for (int i = 3; i >= 0; i--) {
82 str.Append(CFormat(wxT("%08X")) % m_data.u32_data[i]);
83 }
84
85 return str;
86 }
87
88 wxString CUInt128::ToBinaryString(bool trim) const
89 {
90 wxString str;
91 str.Alloc(128);
92 int b;
93 for (int i = 0; i < 128; i++) {
94 b = GetBitNumber(i);
95 if ((!trim) || (b != 0)) {
96 str.Append(b ? wxT("1") : wxT("0"));
97 trim = false;
98 }
99 }
100 if (str.Len() == 0) {
101 str = wxT("0");
102 }
103 return str;
104 }
105
106 CUInt128& CUInt128::SetValueBE(const uint8_t *valueBE) throw()
107 {
108 m_data.u32_data[3] = wxUINT32_SWAP_ON_LE(RawPeekUInt32(valueBE));
109 m_data.u32_data[2] = wxUINT32_SWAP_ON_LE(RawPeekUInt32(valueBE + 4));
110 m_data.u32_data[1] = wxUINT32_SWAP_ON_LE(RawPeekUInt32(valueBE + 8));
111 m_data.u32_data[0] = wxUINT32_SWAP_ON_LE(RawPeekUInt32(valueBE + 12));
112
113 return *this;
114 }
115
116 void CUInt128::ToByteArray(uint8_t *b) const
117 {
118 wxCHECK_RET(b != NULL, wxT("Destination buffer missing."));
119
120 RawPokeUInt32(b, wxUINT32_SWAP_ON_LE(m_data.u32_data[3]));
121 RawPokeUInt32(b + 4, wxUINT32_SWAP_ON_LE(m_data.u32_data[2]));
122 RawPokeUInt32(b + 8, wxUINT32_SWAP_ON_LE(m_data.u32_data[1]));
123 RawPokeUInt32(b + 12, wxUINT32_SWAP_ON_LE(m_data.u32_data[0]));
124 }
125
126 void CUInt128::StoreCryptValue(uint8_t *buf) const
127 {
128 wxCHECK_RET(buf != NULL, wxT("Destination buffer missing."));
129
130 RawPokeUInt32(buf, wxUINT32_SWAP_ON_BE(m_data.u32_data[3]));
131 RawPokeUInt32(buf + 4, wxUINT32_SWAP_ON_BE(m_data.u32_data[2]));
132 RawPokeUInt32(buf + 8, wxUINT32_SWAP_ON_BE(m_data.u32_data[1]));
133 RawPokeUInt32(buf + 12, wxUINT32_SWAP_ON_BE(m_data.u32_data[0]));
134 }
135
136 int CUInt128::CompareTo(const CUInt128 &other) const throw()
137 {
138 for (int i = 3; i >= 0; i--) {
139 if (m_data.u32_data[i] < other.m_data.u32_data[i])
140 return -1;
141 if (m_data.u32_data[i] > other.m_data.u32_data[i])
142 return 1;
143 }
144 return 0;
145 }
146
147 int CUInt128::CompareTo(uint32_t value) const throw()
148 {
149 if ((m_data.u64_data[1] > 0) || (m_data.u32_data[1] > 0) || (m_data.u32_data[0] > value))
150 return 1;
151 if (m_data.u32_data[0] < value)
152 return -1;
153 return 0;
154 }
155
156 CUInt128& CUInt128::Add(const CUInt128 &value) throw()
157 {
158 if (value.IsZero()) return *this;
159
160 int64_t sum = 0;
161 for (int i = 0; i < 4; i++) {
162 sum += m_data.u32_data[i];
163 sum += value.m_data.u32_data[i];
164 m_data.u32_data[i] = (uint32_t)sum;
165 sum >>= 32;
166 }
167 return *this;
168 }
169
170 CUInt128& CUInt128::Subtract(const CUInt128 &value) throw()
171 {
172 if (value.IsZero()) return *this;
173
174 int64_t sum = 0;
175 for (int i = 0; i < 4; i++) {
176 sum += m_data.u32_data[i];
177 sum -= value.m_data.u32_data[i];
178 m_data.u32_data[i] = (uint32_t)sum;
179 sum >>= 32;
180 }
181 return *this;
182 }
183
184 CUInt128& CUInt128::ShiftLeft(unsigned bits) throw()
185 {
186 if ((bits == 0) || IsZero())
187 return *this;
188
189 if (bits > 127) {
190 SetValue((uint32_t)0);
191 return *this;
192 }
193
194 union {
195 uint32_t u32_data[4];
196 uint64_t u64_data[2];
197 } result = {{ 0, 0, 0, 0 }};
198 int indexShift = (int)bits / 32;
199 int64_t shifted = 0;
200 for (int i = 3; i >= indexShift; i--)
201 {
202 shifted += ((int64_t)m_data.u32_data[3 - i]) << (bits % 32);
203 result.u32_data[3 - i + indexShift] = (uint32_t)shifted;
204 shifted = shifted >> 32;
205 }
206 m_data.u64_data[0] = result.u64_data[0];
207 m_data.u64_data[1] = result.u64_data[1];
208
209 return *this;
210 }
211 // File_checked_for_headers
212