File indexing completed on 2025-01-05 04:37:11
0001 /* 0002 SPDX-FileCopyrightText: 2005 Joris Guisson <joris.guisson@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 #include "key.h" 0007 0008 #include <QRandomGenerator> 0009 0010 #include <algorithm> 0011 #include <util/constants.h> 0012 0013 #if defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) 0014 #include <sys/endian.h> 0015 #else 0016 #include <endian.h> 0017 #endif 0018 0019 using namespace bt; 0020 0021 namespace dht 0022 { 0023 Key::Key() 0024 { 0025 } 0026 0027 Key::Key(const bt::SHA1Hash &k) 0028 : bt::SHA1Hash(k) 0029 { 0030 } 0031 0032 Key::Key(const bt::Uint8 *d) 0033 : bt::SHA1Hash(d) 0034 { 0035 } 0036 0037 Key::Key(const QByteArray &ba) 0038 { 0039 memcpy(hash, ba.data(), std::min(20, static_cast<int>(ba.size()))); 0040 } 0041 0042 Key::~Key() 0043 { 0044 } 0045 0046 bool Key::operator==(const Key &other) const 0047 { 0048 return bt::SHA1Hash::operator==(other); 0049 } 0050 0051 bool Key::operator!=(const Key &other) const 0052 { 0053 return !operator==(other); 0054 } 0055 0056 bool Key::operator<(const Key &other) const 0057 { 0058 return memcmp(hash, other.hash, 20) < 0; 0059 } 0060 0061 bool Key::operator<=(const Key &other) const 0062 { 0063 return memcmp(hash, other.hash, 20) <= 0; 0064 } 0065 0066 bool Key::operator>(const Key &other) const 0067 { 0068 return memcmp(hash, other.hash, 20) > 0; 0069 } 0070 0071 bool Key::operator>=(const Key &other) const 0072 { 0073 return memcmp(hash, other.hash, 20) >= 0; 0074 } 0075 0076 Key operator+(const dht::Key &a, const dht::Key &b) 0077 { 0078 dht::Key result; 0079 bt::Uint64 sum = 0; 0080 0081 for (int i = 4; i >= 0; i--) { 0082 sum += (bt::Uint64)htobe32(a.hash[i]) + htobe32(b.hash[i]); 0083 result.hash[i] = htobe32(sum & 0xFFFFFFFF); 0084 sum = sum >> 32; 0085 } 0086 0087 return result; 0088 } 0089 0090 Key operator+(const Key &a, bt::Uint8 value) 0091 { 0092 dht::Key result(a); 0093 0094 bt::Uint64 sum = value; 0095 for (int i = 4; i >= 0 && sum != 0; i--) { 0096 sum += htobe32(result.hash[i]); 0097 result.hash[i] = htobe32(sum & 0xFFFFFFFF); 0098 sum = sum >> 32; 0099 } 0100 0101 return result; 0102 } 0103 0104 Key Key::operator/(int value) const 0105 { 0106 dht::Key result; 0107 bt::Uint64 remainder = 0; 0108 0109 for (int i = 0; i < 5; i++) { 0110 const bt::Uint32 h = htobe32(hash[i]); 0111 result.hash[i] = htobe32((h + remainder) / value); 0112 remainder = ((h + remainder) % value) << 32; 0113 } 0114 0115 return result; 0116 } 0117 0118 Key Key::distance(const Key &a, const Key &b) 0119 { 0120 return a ^ b; 0121 } 0122 0123 Key Key::random() 0124 { 0125 Key k; 0126 Uint32 *h = k.hash; 0127 for (int i = 0; i < 5; i++) { 0128 h[i] = QRandomGenerator::global()->generate(); 0129 } 0130 return k; 0131 } 0132 0133 Key operator-(const Key &a, const Key &b) 0134 { 0135 dht::Key result; 0136 bt::Uint32 carry = 0; 0137 for (int i = 4; i >= 0; i--) { 0138 const bt::Uint32 a32 = htobe32(a.hash[i]); 0139 const bt::Uint32 b32 = htobe32(b.hash[i]); 0140 if (a32 >= ((bt::Uint64)b32 + carry)) { 0141 result.hash[i] = htobe32(a32 - b32 - carry); 0142 carry = 0; 0143 } else { 0144 const bt::Uint64 max = 0xFFFFFFFF + 1; 0145 result.hash[i] = htobe32((bt::Uint32)(max - (b32 - a32) - carry)); 0146 carry = 1; 0147 } 0148 } 0149 0150 return result; 0151 } 0152 0153 Key Key::mid(const dht::Key &a, const dht::Key &b) 0154 { 0155 if (a <= b) 0156 return a + (b - a) / 2; 0157 else 0158 return b + (a - b) / 2; 0159 } 0160 0161 #define rep4(v) v, v, v, v 0162 #define rep20(v) rep4(v), rep4(v), rep4(v), rep4(v), rep4(v) 0163 const bt::Uint8 val_max[20] = {rep20(0xFF)}; 0164 const bt::Uint8 val_min[20] = {rep20(0x00)}; 0165 0166 Key Key::max() 0167 { 0168 return Key(val_max); 0169 } 0170 0171 Key Key::min() 0172 { 0173 return Key(val_min); 0174 } 0175 0176 }