24 #include <msgpack.hpp> 27 #include <netinet/in.h> 30 typedef uint16_t in_port_t;
35 typedef uint16_t sa_family_t;
36 typedef uint16_t in_port_t;
53 OPENDHT_PUBLIC
void hash(
const uint8_t* data,
size_t data_length, uint8_t*
hash,
size_t hash_length);
62 class OPENDHT_PUBLIC
Hash {
64 using T = std::array<uint8_t, N>;
65 typedef typename T::iterator iterator;
66 typedef typename T::const_iterator const_iterator;
71 Hash (
const uint8_t* h,
size_t data_len) {
75 std::copy_n(h, N, data_.begin());
82 explicit Hash(
const std::string& hex);
84 Hash(
const msgpack::object& o) {
88 size_t size()
const {
return data_.size(); }
89 const uint8_t* data()
const {
return data_.data(); }
90 uint8_t* data() {
return data_.data(); }
91 iterator begin() {
return data_.begin(); }
92 const_iterator cbegin()
const {
return data_.cbegin(); }
93 iterator end() {
return data_.end(); }
94 const_iterator cend()
const {
return data_.cend(); }
96 bool operator==(
const Hash& h)
const {
97 auto a =
reinterpret_cast<const uint32_t*
>(data_.data());
98 auto b =
reinterpret_cast<const uint32_t*
>(h.data_.data());
99 constexpr
unsigned n = N /
sizeof(uint32_t);
100 for (
unsigned i=0; i < n; i++)
105 bool operator!=(
const Hash& h)
const {
return !(*
this == h); }
107 bool operator<(
const Hash& o)
const {
108 for(
unsigned i = 0; i < N; i++) {
109 if(data_[i] != o.data_[i])
110 return data_[i] < o.data_[i];
115 explicit operator bool()
const {
116 auto a =
reinterpret_cast<const uint32_t*
>(data_.data());
117 auto b =
reinterpret_cast<const uint32_t*
>(data_.data() + N);
118 for (; a != b; a++) {
125 uint8_t& operator[](
size_t index) {
return data_[index]; }
126 const uint8_t& operator[](
size_t index)
const {
return data_[index]; }
134 for(i = N-1; i >= 0; i--)
139 for(j = 7; j >= 0; j--)
140 if((data_[i] & (0x80 >> j)) != 0)
150 return std::memcmp(id1.data_.data(), id2.data_.data(), N);
154 static inline unsigned 159 for(i = 0; i < N; i++) {
160 if(id1.data_[i] != id2.data_[i])
167 x = id1.data_[i] ^ id2.data_[i];
170 while((x & 0x80) == 0) {
182 for(
unsigned i = 0; i < N; i++) {
184 if(id1.data_[i] == id2.data_[i])
186 xor1 = id1.data_[i] ^ data_[i];
187 xor2 = id2.data_[i] ^ data_[i];
197 getBit(
unsigned nbit)
const 199 auto& num = *(data_.cbegin()+(nbit/8));
200 unsigned bit = 7 - (nbit % 8);
201 return (num >> bit) & 1;
205 setBit(
unsigned nbit,
bool b)
207 auto& num = data_[nbit/8];
208 unsigned bit = 7 - (nbit % 8);
209 num ^= (-b ^ num) & (1 << bit);
212 double toFloat()
const {
215 for (
size_t i = 0; i < std::min<size_t>(N,
sizeof(D)-1); i++)
216 v += *(data_.cbegin()+i) / (
double)((D)1 << 8*(i+1));
220 static inline Hash
get(
const std::string& data) {
221 return get((
const uint8_t*)data.data(), data.size());
224 static inline Hash
get(
const std::vector<uint8_t>& data) {
225 return get(data.data(), data.size());
231 static Hash get(
const uint8_t* data,
size_t data_len)
238 static Hash getRandom();
241 OPENDHT_PUBLIC
friend std::ostream& operator<< (std::ostream& s, const Hash<M>& h);
244 OPENDHT_PUBLIC
friend std::istream& operator>> (std::istream& s,
Hash<M>& h);
246 const char* to_c_str()
const;
248 std::string toString()
const;
250 template <
typename Packer>
251 void msgpack_pack(Packer& pk)
const 254 pk.pack_bin_body((
char*)data_.data(), N);
257 void msgpack_unpack(msgpack::object o) {
258 if (o.type != msgpack::type::BIN or o.via.bin.size != N)
259 throw msgpack::type_error();
260 std::copy_n(o.via.bin.ptr, N, data_.data());
264 void fromString(
const char*);
268 using InfoHash = Hash<HASH_LEN>;
269 using h256 = Hash<32>;
273 std::ostream& operator<< (std::ostream& s, const Hash<N>& h)
275 s.write(h.to_c_str(), N*2);
280 std::istream& operator>> (std::istream& s, Hash<N>& h)
282 std::array<char, h.size()*2> dat;
283 s.exceptions(std::istream::eofbit | std::istream::failbit);
284 s.read(&(*dat.begin()), dat.size());
285 fromString(dat.data());
291 if (hex.size() < 2*N)
294 fromString(hex.c_str());
300 auto hex2bin = [](
char c) -> uint8_t {
301 if (c >=
'a' and c <=
'f')
return 10 + c -
'a';
302 else if (c >=
'A' and c <=
'F')
return 10 + c -
'A';
303 else if (c >=
'0' and c <=
'9')
return c -
'0';
304 else throw std::domain_error(
"not an hex character");
307 for (
size_t i=0; i<N; i++)
308 data_[i] = (hex2bin(in[2*i]) << 4) | hex2bin(in[2*i+1]);
309 }
catch (
const std::domain_error&) {
319 crypto::random_device rdev;
320 std::uniform_int_distribution<uint32_t> rand_int;
321 auto a =
reinterpret_cast<uint32_t*
>(h.data());
322 auto b =
reinterpret_cast<uint32_t*
>(h.data() + h.size());
323 std::generate(a, b, std::bind(rand_int, std::ref(rdev)));
327 struct HexMap :
public std::array<std::array<char, 2>, 256> {
329 for (
size_t i=0; i<size(); i++) {
330 auto& e = (*this)[i];
331 e[0] = hex_digits[(i >> 4) & 0x0F];
332 e[1] = hex_digits[i & 0x0F];
336 static constexpr
const char* hex_digits =
"0123456789abcdef";
339 OPENDHT_PUBLIC
extern const HexMap hex_map;
345 thread_local std::array<char, N*2+1> buf;
346 for (
size_t i=0; i<N; i++) {
347 auto b = buf.data()+i*2;
348 const auto& m = hex_map[data_[i]];
349 *((uint16_t*)b) = *((uint16_t*)&m);
356 Hash<N>::toString()
const 358 return std::string(to_c_str(), N*2);
361 const InfoHash zeroes {};
368 template <
typename Packer>
369 void msgpack_pack(Packer& pk)
const 372 pk.pack(std::string(
"id"));
374 pk.pack(std::string(
"addr"));
376 pk.pack_bin_body((
char*)&ss, sslen);
379 void msgpack_unpack(msgpack::object o);
381 OPENDHT_PUBLIC
friend std::ostream& operator<< (std::ostream& s,
const NodeExport& h);
OPENDHT_PUBLIC Blob hash(const Blob &data, size_t hash_length=512/8)
static int cmp(const Hash &id1, const Hash &id2)
static unsigned commonBits(const Hash &id1, const Hash &id2)
int xorCmp(const Hash &id1, const Hash &id2) const