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