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 }