27#include <netinet/in.h>
30typedef uint16_t in_port_t;
35typedef uint16_t sa_family_t;
36typedef uint16_t in_port_t;
55 OPENDHT_PUBLIC
void hash(
const uint8_t* data,
size_t data_length, uint8_t*
hash,
size_t hash_length);
66 using T = std::array<uint8_t, N>;
67 typedef typename T::iterator iterator;
68 typedef typename T::const_iterator const_iterator;
73 Hash(
const uint8_t* h,
size_t data_len) {
77 std::copy_n(h, N, data_.begin());
84 explicit Hash(std::string_view hex) {
88 fromString(hex.data());
91 Hash(
const msgpack::object& o) {
95 static constexpr size_t size() noexcept {
return N; }
96 const uint8_t* data()
const {
return data_.data(); }
97 uint8_t* data() {
return data_.data(); }
98 iterator begin() {
return data_.begin(); }
99 const_iterator cbegin()
const {
return data_.cbegin(); }
100 iterator end() {
return data_.end(); }
101 const_iterator cend()
const {
return data_.cend(); }
103 static constexpr inline Hash zero() noexcept {
return Hash{}; }
105 bool operator==(
const Hash& h)
const {
106 auto a =
reinterpret_cast<const uint32_t*
>(data_.data());
107 auto b =
reinterpret_cast<const uint32_t*
>(h.data_.data());
108 constexpr unsigned n = N /
sizeof(uint32_t);
109 for (
unsigned i=0; i < n; i++)
114 bool operator!=(
const Hash& h)
const {
return !(*
this == h); }
116 bool operator<(
const Hash& o)
const {
117 for(
unsigned i = 0; i < N; i++) {
118 if(data_[i] != o.data_[i])
119 return data_[i] < o.data_[i];
124 Hash operator^(
const Hash& o)
const {
126 for(
auto i = 0u; i < N; i++) {
127 result[i] = data_[i] ^ o.data_[i];
132 explicit operator bool()
const {
133 auto a =
reinterpret_cast<const uint32_t*
>(data_.data());
134 auto b =
reinterpret_cast<const uint32_t*
>(data_.data() + N);
135 for (; a != b; a++) {
142 uint8_t& operator[](
size_t index) {
return data_[index]; }
143 const uint8_t& operator[](
size_t index)
const {
return data_[index]; }
151 for(i = N-1; i >= 0; i--)
156 for(j = 7; j >= 0; j--)
157 if((data_[i] & (0x80 >> j)) != 0)
162 static inline int cmp(
const Hash& id1,
const Hash& id2) {
163 return std::memcmp(id1.data_.data(), id2.data_.data(), N);
167 static inline unsigned
172 for(i = 0; i < N; i++) {
173 if(id1.data_[i] != id2.data_[i])
180 x = id1.data_[i] ^ id2.data_[i];
183 while((x & 0x80) == 0) {
195 for (
unsigned i = 0; i < N; i++) {
196 if(id1.data_[i] == id2.data_[i])
198 uint8_t xor1 = id1.data_[i] ^ data_[i];
199 uint8_t xor2 = id2.data_[i] ^ data_[i];
200 return (xor1 < xor2) ? -1 : 1;
206 getBit(
unsigned nbit)
const
208 auto& num = *(data_.cbegin()+(nbit/8));
209 unsigned bit = 7 - (nbit % 8);
210 return (num >> bit) & 1;
214 setBit(
unsigned nbit,
bool b)
216 auto& num = data_[nbit/8];
217 unsigned bit = 7 - (nbit % 8);
218 num ^= (-b ^ num) & (1 << bit);
221 double toFloat()
const {
224 for (
size_t i = 0; i < std::min<size_t>(N,
sizeof(D)-1); i++)
225 v += *(data_.cbegin()+i) / (
double)((D)1 << 8*(i+1));
229 static inline Hash get(std::string_view data) {
230 return get((
const uint8_t*)data.data(), data.size());
233 static inline Hash get(
const std::vector<uint8_t>& data) {
234 return get(data.data(), data.size());
240 static Hash get(
const uint8_t* data,
size_t data_len)
243 crypto::hash(data, data_len, ret.data(), N);
247 static Hash getRandom();
249 template <
typename Rd>
250 static Hash getRandom(Rd&);
253 OPENDHT_PUBLIC
friend std::ostream& operator<< (std::ostream& s,
const Hash<M>& h);
256 OPENDHT_PUBLIC
friend std::istream& operator>> (std::istream& s,
Hash<M>& h);
258 const char* to_c_str()
const;
260 std::string toString()
const;
262 template <
typename Packer>
263 void msgpack_pack(Packer& pk)
const
266 pk.pack_bin_body((
char*)data_.data(), N);
269 void msgpack_unpack(msgpack::object o) {
270 if (o.type != msgpack::type::BIN or o.via.bin.size != N)
271 throw msgpack::type_error();
272 std::copy_n(o.via.bin.ptr, N, data_.data());
276 void fromString(
const char*);
280using InfoHash = Hash<HASH_LEN>;
281using h256 = Hash<32>;
285std::ostream& operator<< (std::ostream& s,
const Hash<N>& h)
287 s.write(h.to_c_str(), N*2);
292std::istream& operator>> (std::istream& s, Hash<N>& h)
294 std::array<char, h.size()*2> dat;
295 s.exceptions(std::istream::eofbit | std::istream::failbit);
296 s.read(&(*dat.begin()), dat.size());
297 fromString(dat.data());
303Hash<N>::fromString(
const char* in) {
304 auto hex2bin = [](
char c) -> uint8_t {
305 if (c >=
'a' and c <=
'f')
return 10 + c -
'a';
306 else if (c >=
'A' and c <=
'F')
return 10 + c -
'A';
307 else if (c >=
'0' and c <=
'9')
return c -
'0';
308 else throw std::domain_error(
"not an hex character");
311 for (
size_t i=0; i<N; i++)
312 data_[i] = (hex2bin(in[2*i]) << 4) | hex2bin(in[2*i+1]);
313 }
catch (
const std::domain_error&) {
323 crypto::random_device rdev;
324 std::uniform_int_distribution<uint32_t> rand_int;
325 auto a =
reinterpret_cast<uint32_t*
>(h.data());
326 auto b =
reinterpret_cast<uint32_t*
>(h.data() + h.size());
327 std::generate(a, b, std::bind(rand_int, std::ref(rdev)));
332template <
typename Rd>
334Hash<N>::getRandom(Rd& rdev)
337 std::uniform_int_distribution<uint32_t> rand_int;
338 auto a =
reinterpret_cast<uint32_t*
>(h.data());
339 auto b =
reinterpret_cast<uint32_t*
>(h.data() + h.size());
340 std::generate(a, b, std::bind(rand_int, std::ref(rdev)));
344struct alignas(std::max_align_t)
HexMap :
public std::array<std::array<char, 2>, 256> {
346 for (
size_t i=0; i<size(); i++) {
347 auto& e = (*this)[i];
348 e[0] = hex_digits[(i >> 4) & 0x0F];
349 e[1] = hex_digits[i & 0x0F];
353 static constexpr const char* hex_digits =
"0123456789abcdef";
356OPENDHT_PUBLIC
extern const HexMap hex_map;
359toHex(
const uint8_t* data,
size_t size) {
360 std::string ret(size * 2,
'\0');
361 for (
size_t i=0; i<size; i++) {
362 auto b = ret.data()+i*2;
363 const auto& m = hex_map[data[i]];
364 *((uint16_t*)b) = *((uint16_t*)&m);
370toHex(
const std::vector<uint8_t>& data) {
371 return toHex(data.data(), data.size());
376Hash<N>::to_c_str()
const
378 alignas(std::max_align_t)
thread_local std::array<char, N*2+1> buf;
379 for (
size_t i=0; i<N; i++) {
380 auto b = buf.data()+i*2;
381 const auto& m = hex_map[data_[i]];
382 *((uint16_t*)b) = *((uint16_t*)&m);
389Hash<N>::toString()
const
391 return std::string(to_c_str(), N*2);
399 template <
typename Packer>
400 void msgpack_pack(Packer& pk)
const
403 pk.pack(std::string(
"id"));
405 pk.pack(std::string(
"addr"));
407 pk.pack_bin_body((
char*)&ss, sslen);
410 void msgpack_unpack(msgpack::object o);
412 OPENDHT_PUBLIC
friend std::ostream& operator<< (std::ostream& s,
const NodeExport& h);
static unsigned commonBits(const Hash &id1, const Hash &id2)
Hash(std::string_view hex)
static Hash get(const uint8_t *data, size_t data_len)
int xorCmp(const Hash &id1, const Hash &id2) const
OPENDHT_PUBLIC Blob hash(const Blob &data, size_t hash_length=512/8)