C++ Distributed Hash Table
value.h
1 /*
2  * Copyright (C) 2014-2017 Savoir-faire Linux Inc.
3  * Author(s) : Adrien BĂ©raud <adrien.beraud@savoirfairelinux.com>
4  * Simon DĂ©saulniers <simon.desaulniers@savoirfairelinux.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 #pragma once
21 
22 #include "infohash.h"
23 #include "crypto.h"
24 #include "utils.h"
25 #include "sockaddr.h"
26 
27 #include <msgpack.hpp>
28 
29 #include <string>
30 #include <sstream>
31 #include <bitset>
32 #include <vector>
33 #include <iostream>
34 #include <algorithm>
35 #include <functional>
36 #include <memory>
37 #include <chrono>
38 #include <set>
39 
40 #ifdef OPENDHT_JSONCPP
41 #include <json/json.h>
42 #endif
43 
44 namespace dht {
45 
46 struct Value;
47 struct Query;
48 
59 using StorePolicy = std::function<bool(InfoHash key, std::shared_ptr<Value>& value, const InfoHash& from, const SockAddr& addr)>;
60 
75 using EditPolicy = std::function<bool(InfoHash key, const std::shared_ptr<Value>& old_val, std::shared_ptr<Value>& new_val, const InfoHash& from, const SockAddr& addr)>;
76 
77 static constexpr const size_t MAX_VALUE_SIZE {1024 * 64};
78 
79 struct OPENDHT_PUBLIC ValueType {
80  typedef uint16_t Id;
81 
82  static bool DEFAULT_STORE_POLICY(InfoHash, std::shared_ptr<Value>& v, const InfoHash&, const SockAddr&);
83  static bool DEFAULT_EDIT_POLICY(InfoHash, const std::shared_ptr<Value>&, std::shared_ptr<Value>&, const InfoHash&, const SockAddr&) {
84  return false;
85  }
86 
87  ValueType () {}
88 
89  ValueType (Id id, std::string name, duration e = std::chrono::minutes(10))
90  : id(id), name(name), expiration(e) {}
91 
92  ValueType (Id id, std::string name, duration e, StorePolicy sp, EditPolicy ep = DEFAULT_EDIT_POLICY)
93  : id(id), name(name), expiration(e), storePolicy(sp), editPolicy(ep) {}
94 
95  virtual ~ValueType() {}
96 
97  bool operator==(const ValueType& o) {
98  return id == o.id;
99  }
100 
101  // Generic value type
102  static const ValueType USER_DATA;
103 
104 
105  Id id {0};
106  std::string name {};
107  duration expiration {60 * 10};
108  StorePolicy storePolicy {DEFAULT_STORE_POLICY};
109  EditPolicy editPolicy {DEFAULT_EDIT_POLICY};
110 };
111 
112 class TypeStore {
113 public:
114  void registerType(const ValueType& type) {
115  types[type.id] = type;
116  }
117  const ValueType& getType(ValueType::Id type_id) const {
118  const auto& t_it = types.find(type_id);
119  return (t_it == types.end()) ? ValueType::USER_DATA : t_it->second;
120  }
121 private:
122  std::map<ValueType::Id, ValueType> types {};
123 };
124 
134 struct OPENDHT_PUBLIC Value
135 {
136  enum class Field : int {
137  None = 0,
138  Id, /* Value::id */
139  ValueType, /* Value::type */
140  OwnerPk, /* Value::owner */
141  SeqNum, /* Value::seq */
142  UserType, /* Value::user_type */
143 
144  COUNT /* the total number of fields */
145  };
146 
147  typedef uint64_t Id;
148  static const constexpr Id INVALID_ID {0};
149 
150  class Filter : public std::function<bool(const Value&)> {
151  public:
152  Filter() {}
153 
154  template<typename Functor>
155  Filter(Functor f) : std::function<bool(const Value&)>::function(f) {}
156 
157  Filter chain(Filter&& f2) {
158  auto f1 = *this;
159  return chain(std::move(f1), std::move(f2));
160  }
161  Filter chainOr(Filter&& f2) {
162  auto f1 = *this;
163  return chainOr(std::move(f1), std::move(f2));
164  }
165  static Filter chain(Filter&& f1, Filter&& f2) {
166  if (not f1) return f2;
167  if (not f2) return f1;
168  return [f1,f2](const Value& v) {
169  return f1(v) and f2(v);
170  };
171  }
172  static Filter chainAll(std::vector<Filter>&& set) {
173  if (set.empty()) return {};
174  return std::bind([](const Value& v, std::vector<Filter>& s) {
175  for (const auto& f : s)
176  if (f and not f(v))
177  return false;
178  return true;
179  }, std::placeholders::_1, std::move(set));
180  }
181  static Filter chain(std::initializer_list<Filter> l) {
182  return chainAll(std::vector<Filter>(l.begin(), l.end()));
183  }
184  static Filter chainOr(Filter&& f1, Filter&& f2) {
185  if (not f1 or not f2) return AllFilter();
186  return [f1,f2](const Value& v) {
187  return f1(v) or f2(v);
188  };
189  }
190  std::vector<Sp<Value>> filter(const std::vector<Sp<Value>>& values) {
191  if (not (*this))
192  return values;
193  std::vector<Sp<Value>> ret;
194  for (const auto& v : values)
195  if ((*this)(v))
196  ret.emplace_back(v);
197  return ret;
198  }
199  };
200 
201  /* Sneaky functions disguised in classes */
202 
203  static const Filter AllFilter() {
204  return {};
205  }
206 
207  static Filter TypeFilter(const ValueType& t) {
208  const auto tid = t.id;
209  return [tid](const Value& v) {
210  return v.type == tid;
211  };
212  }
213  static Filter TypeFilter(const ValueType::Id& tid) {
214  return [tid](const Value& v) {
215  return v.type == tid;
216  };
217  }
218 
219  static Filter IdFilter(const Id id) {
220  return [id](const Value& v) {
221  return v.id == id;
222  };
223  }
224 
225  static Filter RecipientFilter(const InfoHash& r) {
226  return [r](const Value& v) {
227  return v.recipient == r;
228  };
229  }
230 
231  static Filter OwnerFilter(const crypto::PublicKey& pk) {
232  return OwnerFilter(pk.getId());
233  }
234 
235  static Filter OwnerFilter(const InfoHash& pkh) {
236  return [pkh](const Value& v) {
237  return v.owner and v.owner->getId() == pkh;
238  };
239  }
240 
241  static Filter SeqNumFilter(uint16_t seq_no) {
242  return [seq_no](const Value& v) {
243  return v.seq == seq_no;
244  };
245  }
246 
247  static Filter UserTypeFilter(const std::string& ut) {
248  return [ut](const Value& v) {
249  return v.user_type == ut;
250  };
251  }
252 
254  {
255  public:
256  SerializableBase() {}
257  virtual ~SerializableBase() {};
258  virtual const ValueType& getType() const = 0;
259  virtual void unpackValue(const Value& v) = 0;
260  virtual Value packValue() const = 0;
261  };
262 
263  template <typename Derived, typename Base=SerializableBase>
264  class Serializable : public Base
265  {
266  public:
267  using Base::Base;
268 
269  virtual const ValueType& getType() const {
270  return Derived::TYPE;
271  }
272 
273  virtual void unpackValue(const Value& v) {
274  auto msg = msgpack::unpack((const char*)v.data.data(), v.data.size());
275  msg.get().convert(*static_cast<Derived*>(this));
276  }
277 
278  virtual Value packValue() const {
279  return Value {getType(), static_cast<const Derived&>(*this)};
280  }
281  };
282 
283  template <typename T,
284  typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
285  static Value pack(const T& obj)
286  {
287  return obj.packValue();
288  }
289 
290  template <typename T,
291  typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
292  static Value pack(const T& obj)
293  {
294  return {ValueType::USER_DATA.id, packMsg<T>(obj)};
295  }
296 
297  template <typename T,
298  typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
299  static T unpack(const Value& v)
300  {
301  T msg;
302  msg.unpackValue(v);
303  return msg;
304  }
305 
306  template <typename T,
307  typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
308  static T unpack(const Value& v)
309  {
310  return unpackMsg<T>(v.data);
311  }
312 
313  template <typename T>
314  T unpack()
315  {
316  return unpack<T>(*this);
317  }
318 
319  bool isEncrypted() const {
320  return not cypher.empty();
321  }
322  bool isSigned() const {
323  return owner and not signature.empty();
324  }
325 
331  void sign(const crypto::PrivateKey& key) {
332  if (isEncrypted())
333  throw DhtException("Can't sign encrypted data.");
334  owner = std::make_shared<const crypto::PublicKey>(key.getPublicKey());
335  signature = key.sign(getToSign());
336  }
337 
342  bool checkSignature() const {
343  return isSigned() and owner->checkSignature(getToSign(), signature);
344  }
345 
346  std::shared_ptr<const crypto::PublicKey> getOwner() const {
347  return std::static_pointer_cast<const crypto::PublicKey>(owner);
348  }
349 
354  if (isEncrypted())
355  throw DhtException("Data is already encrypted.");
356  setRecipient(to.getId());
357  sign(from);
358  Value nv {id};
359  nv.setCypher(to.encrypt(getToEncrypt()));
360  return nv;
361  }
362 
363  Value() {}
364 
365  Value (Id id) : id(id) {}
366 
368  Value(ValueType::Id t, const Blob& data, Id id = INVALID_ID)
369  : id(id), type(t), data(data) {}
370  Value(ValueType::Id t, Blob&& data, Id id = INVALID_ID)
371  : id(id), type(t), data(std::move(data)) {}
372  Value(ValueType::Id t, const uint8_t* dat_ptr, size_t dat_len, Id id = INVALID_ID)
373  : id(id), type(t), data(dat_ptr, dat_ptr+dat_len) {}
374 
375 #ifdef OPENDHT_JSONCPP
376 
380  Value(Json::Value& json);
381 #endif
382 
383  template <typename Type>
384  Value(ValueType::Id t, const Type& d, Id id = INVALID_ID)
385  : id(id), type(t), data(packMsg(d)) {}
386 
387  template <typename Type>
388  Value(const ValueType& t, const Type& d, Id id = INVALID_ID)
389  : id(id), type(t.id), data(packMsg(d)) {}
390 
392  Value(const Blob& userdata) : data(userdata) {}
393  Value(Blob&& userdata) : data(std::move(userdata)) {}
394  Value(const uint8_t* dat_ptr, size_t dat_len) : data(dat_ptr, dat_ptr+dat_len) {}
395 
396  Value(Value&& o) noexcept
397  : id(o.id), owner(std::move(o.owner)), recipient(o.recipient),
398  type(o.type), data(std::move(o.data)), user_type(std::move(o.user_type)), seq(o.seq), signature(std::move(o.signature)), cypher(std::move(o.cypher)) {}
399 
400  template <typename Type>
401  Value(const Type& vs)
402  : Value(pack<Type>(vs)) {}
403 
407  Value(const msgpack::object& o) {
408  msgpack_unpack(o);
409  }
410 
411  inline bool operator== (const Value& o) {
412  return id == o.id &&
413  (isEncrypted() ? cypher == o.cypher :
414  ((owner == o.owner || *owner == *o.owner) && type == o.type && data == o.data && user_type == o.user_type && signature == o.signature));
415  }
416 
417  void setRecipient(const InfoHash& r) {
418  recipient = r;
419  }
420 
421  void setCypher(Blob&& c) {
422  cypher = std::move(c);
423  }
424 
428  Blob getToSign() const {
429  msgpack::sbuffer buffer;
430  msgpack::packer<msgpack::sbuffer> pk(&buffer);
431  msgpack_pack_to_sign(pk);
432  return {buffer.data(), buffer.data()+buffer.size()};
433  }
434 
438  Blob getToEncrypt() const {
439  msgpack::sbuffer buffer;
440  msgpack::packer<msgpack::sbuffer> pk(&buffer);
441  msgpack_pack_to_encrypt(pk);
442  return {buffer.data(), buffer.data()+buffer.size()};
443  }
444 
446  OPENDHT_PUBLIC friend std::ostream& operator<< (std::ostream& s, const Value& v);
447 
448  std::string toString() const {
449  std::stringstream ss;
450  ss << *this;
451  return ss.str();
452  }
453 
454 #ifdef OPENDHT_JSONCPP
455 
463  Json::Value toJson() const;
464 #endif
465 
467  size_t size() const;
468 
469  template <typename Packer>
470  void msgpack_pack_to_sign(Packer& pk) const
471  {
472  bool has_owner = owner && *owner;
473  pk.pack_map((user_type.empty()?0:1) + (has_owner?(recipient ? 5 : 4):2));
474  if (has_owner) { // isSigned
475  pk.pack(std::string("seq")); pk.pack(seq);
476  pk.pack(std::string("owner")); owner->msgpack_pack(pk);
477  if (recipient) {
478  pk.pack(std::string("to")); pk.pack(recipient);
479  }
480  }
481  pk.pack(std::string("type")); pk.pack(type);
482  pk.pack(std::string("data")); pk.pack_bin(data.size());
483  pk.pack_bin_body((const char*)data.data(), data.size());
484  if (not user_type.empty()) {
485  pk.pack(std::string("utype")); pk.pack(user_type);
486  }
487  }
488 
489  template <typename Packer>
490  void msgpack_pack_to_encrypt(Packer& pk) const
491  {
492  if (isEncrypted()) {
493  pk.pack_bin(cypher.size());
494  pk.pack_bin_body((const char*)cypher.data(), cypher.size());
495  } else {
496  pk.pack_map(isSigned() ? 2 : 1);
497  pk.pack(std::string("body")); msgpack_pack_to_sign(pk);
498  if (isSigned()) {
499  pk.pack(std::string("sig")); pk.pack_bin(signature.size());
500  pk.pack_bin_body((const char*)signature.data(), signature.size());
501  }
502  }
503  }
504 
505  template <typename Packer>
506  void msgpack_pack(Packer& pk) const
507  {
508  pk.pack_map(2);
509  pk.pack(std::string("id")); pk.pack(id);
510  pk.pack(std::string("dat")); msgpack_pack_to_encrypt(pk);
511  }
512 
513  template <typename Packer>
514  void msgpack_pack_fields(const std::set<Value::Field>& fields, Packer& pk) const
515  {
516  for (const auto& field : fields)
517  switch (field) {
518  case Value::Field::Id:
519  pk.pack(static_cast<uint64_t>(id));
520  break;
521  case Value::Field::ValueType:
522  pk.pack(static_cast<uint64_t>(type));
523  break;
524  case Value::Field::OwnerPk:
525  if (owner)
526  owner->msgpack_pack(pk);
527  else
528  InfoHash().msgpack_pack(pk);
529  break;
530  case Value::Field::SeqNum:
531  pk.pack(static_cast<uint64_t>(seq));
532  break;
533  case Value::Field::UserType:
534  pk.pack(user_type);
535  break;
536  default:
537  break;
538  }
539  }
540 
541  void msgpack_unpack(msgpack::object o);
542  void msgpack_unpack_body(const msgpack::object& o);
543  Blob getPacked() const {
544  msgpack::sbuffer buffer;
545  msgpack::packer<msgpack::sbuffer> pk(&buffer);
546  pk.pack(*this);
547  return {buffer.data(), buffer.data()+buffer.size()};
548  }
549 
550  void msgpack_unpack_fields(const std::set<Value::Field>& fields, const msgpack::object& o, unsigned offset);
551 
552  Id id {INVALID_ID};
553 
557  std::shared_ptr<const crypto::PublicKey> owner {};
558 
564  InfoHash recipient {};
565 
569  ValueType::Id type {ValueType::USER_DATA.id};
570  Blob data {};
571 
575  std::string user_type {};
576 
580  uint16_t seq {0};
581 
585  Blob signature {};
586 
590  Blob cypher {};
591 };
592 
593 using ValuesExport = std::pair<InfoHash, Blob>;
594 
602 struct OPENDHT_PUBLIC FieldValue
603 {
604  FieldValue() {}
605  FieldValue(Value::Field f, uint64_t int_value) : field(f), intValue(int_value) {}
606  FieldValue(Value::Field f, InfoHash hash_value) : field(f), hashValue(hash_value) {}
607  FieldValue(Value::Field f, Blob blob_value) : field(f), blobValue(blob_value) {}
608 
609  bool operator==(const FieldValue& fd) const;
610 
611  // accessors
612  Value::Field getField() const { return field; }
613  uint64_t getInt() const { return intValue; }
614  InfoHash getHash() const { return hashValue; }
615  Blob getBlob() const { return blobValue; }
616 
617  template <typename Packer>
618  void msgpack_pack(Packer& p) const {
619  p.pack_map(2);
620  p.pack(std::string("f")); p.pack(static_cast<uint8_t>(field));
621 
622  p.pack(std::string("v"));
623  switch (field) {
624  case Value::Field::Id:
625  case Value::Field::ValueType:
626  p.pack(intValue);
627  break;
628  case Value::Field::OwnerPk:
629  p.pack(hashValue);
630  break;
631  case Value::Field::UserType:
632  p.pack_bin(blobValue.size());
633  p.pack_bin_body((const char*)blobValue.data(), blobValue.size());
634  break;
635  default:
636  throw msgpack::type_error();
637  }
638  }
639 
640  void msgpack_unpack(msgpack::object msg) {
641  hashValue = {};
642  blobValue.clear();
643 
644  if (auto f = findMapValue(msg, "f"))
645  field = (Value::Field)f->as<unsigned>();
646  else
647  throw msgpack::type_error();
648 
649  auto v = findMapValue(msg, "v");
650  if (not v)
651  throw msgpack::type_error();
652  else
653  switch (field) {
654  case Value::Field::Id:
655  case Value::Field::ValueType:
656  intValue = v->as<decltype(intValue)>();
657  break;
658  case Value::Field::OwnerPk:
659  hashValue = v->as<decltype(hashValue)>();
660  break;
661  case Value::Field::UserType:
662  blobValue = unpackBlob(*v);
663  break;
664  default:
665  throw msgpack::type_error();
666  }
667  }
668 
669  Value::Filter getLocalFilter() const;
670 
671 private:
672  Value::Field field {Value::Field::None};
673  // three possible value types
674  uint64_t intValue {};
675  InfoHash hashValue {};
676  Blob blobValue {};
677 };
678 
686 struct OPENDHT_PUBLIC Select
687 {
688  Select() { }
689  Select(const std::string& q_str);
690 
691  bool isSatisfiedBy(const Select& os) const;
692 
700  Select& field(Value::Field field) {
701  if (std::find(fieldSelection_.begin(), fieldSelection_.end(), field) == fieldSelection_.end())
702  fieldSelection_.emplace_back(field);
703  return *this;
704  }
705 
711  std::set<Value::Field> getSelection() const {
712  return {fieldSelection_.begin(), fieldSelection_.end()};
713  }
714 
715  template <typename Packer>
716  void msgpack_pack(Packer& pk) const { pk.pack(fieldSelection_); }
717  void msgpack_unpack(const msgpack::object& o) {
718  fieldSelection_ = o.as<decltype(fieldSelection_)>();
719  }
720 
721  std::string toString() const {
722  std::stringstream ss;
723  ss << *this;
724  return ss.str();
725  }
726 
727  OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Select& q);
728 private:
729  std::vector<Value::Field> fieldSelection_ {};
730 };
731 
739 struct OPENDHT_PUBLIC Where
740 {
741  Where() { }
742  Where(const std::string& q_str);
743 
744  bool isSatisfiedBy(const Where& where) const;
745 
753  Where& id(Value::Id id) {
754  FieldValue fv {Value::Field::Id, id};
755  if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
756  filters_.emplace_back(std::move(fv));
757  return *this;
758  }
759 
767  Where& valueType(ValueType::Id type) {
768  FieldValue fv {Value::Field::ValueType, type};
769  if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
770  filters_.emplace_back(std::move(fv));
771  return *this;
772  }
773 
781  Where& owner(InfoHash owner_pk_hash) {
782  FieldValue fv {Value::Field::OwnerPk, owner_pk_hash};
783  if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
784  filters_.emplace_back(std::move(fv));
785  return *this;
786  }
787 
795  Where& seq(uint16_t seq_no) {
796  FieldValue fv {Value::Field::SeqNum, seq_no};
797  if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
798  filters_.emplace_back(std::move(fv));
799  return *this;
800  }
801 
809  Where& userType(std::string user_type) {
810  FieldValue fv {Value::Field::UserType, Blob {user_type.begin(), user_type.end()}};
811  if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
812  filters_.emplace_back(std::move(fv));
813  return *this;
814  }
815 
822  if (filters_.empty()) return {};
823  std::vector<Value::Filter> fset;
824  fset.reserve(filters_.size());
825  for (const auto& f : filters_) {
826  if (auto lf = f.getLocalFilter())
827  fset.emplace_back(std::move(lf));
828  }
829  return Value::Filter::chainAll(std::move(fset));
830  }
831 
832  template <typename Packer>
833  void msgpack_pack(Packer& pk) const { pk.pack(filters_); }
834  void msgpack_unpack(const msgpack::object& o) {
835  filters_.clear();
836  filters_ = o.as<decltype(filters_)>();
837  }
838 
839  std::string toString() const {
840  std::stringstream ss;
841  ss << *this;
842  return ss.str();
843  }
844 
845  bool empty() const {
846  return filters_.empty();
847  }
848 
849  OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Where& q);
850 
851 private:
852  std::vector<FieldValue> filters_;
853 };
854 
863 struct OPENDHT_PUBLIC Query
864 {
865  static const std::string QUERY_PARSE_ERROR;
866 
867  Query(Select s = {}, Where w = {}, bool none = false) : select(s), where(w), none(none) { };
868 
882  Query(std::string q_str) {
883  auto pos_W = q_str.find("WHERE");
884  auto pos_w = q_str.find("where");
885  auto pos = std::min(pos_W != std::string::npos ? pos_W : q_str.size(),
886  pos_w != std::string::npos ? pos_w : q_str.size());
887  select = q_str.substr(0, pos);
888  where = q_str.substr(pos, q_str.size()-pos);
889  }
890 
894  bool isSatisfiedBy(const Query& q) const;
895 
896  template <typename Packer>
897  void msgpack_pack(Packer& pk) const {
898  pk.pack_map(2);
899  pk.pack(std::string("s")); pk.pack(select); /* packing field selectors */
900  pk.pack(std::string("w")); pk.pack(where); /* packing filters */
901  }
902 
903  void msgpack_unpack(const msgpack::object& o);
904 
905  std::string toString() const {
906  std::stringstream ss;
907  ss << *this;
908  return ss.str();
909  }
910 
911  OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Query& q) {
912  return s << "Query[" << q.select << " " << q.where << "]";
913  }
914 
915  Select select {};
916  Where where {};
917  bool none {false}; /* When true, any query satisfies this. */
918 };
919 
927 struct OPENDHT_PUBLIC FieldValueIndex {
928  FieldValueIndex() {}
929  FieldValueIndex(const Value& v, Select s = {});
936  bool containedIn(const FieldValueIndex& other) const;
937 
938  OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& os, const FieldValueIndex& fvi);
939 
940  void msgpack_unpack_fields(const std::set<Value::Field>& fields,
941  const msgpack::object& o,
942  unsigned offset);
943 
944  std::map<Value::Field, FieldValue> index {};
945 };
946 
947 template <typename T,
948  typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
950 getFilterSet(Value::Filter f)
951 {
952  return Value::Filter::chain({
953  Value::TypeFilter(T::TYPE),
954  T::getFilter(),
955  f
956  });
957 }
958 
959 template <typename T,
960  typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
961 Value::Filter
962 getFilterSet(Value::Filter f)
963 {
964  return f;
965 }
966 
967 template <typename T,
968  typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
969 Value::Filter
970 getFilterSet()
971 {
972  return Value::Filter::chain({
973  Value::TypeFilter(T::TYPE),
974  T::getFilter()
975  });
976 }
977 
978 template <typename T,
979  typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
980 Value::Filter
981 getFilterSet()
982 {
983  return Value::AllFilter();
984 }
985 
986 template <class T>
987 std::vector<T>
988 unpackVector(const std::vector<std::shared_ptr<Value>>& vals) {
989  std::vector<T> ret;
990  ret.reserve(vals.size());
991  for (const auto& v : vals) {
992  try {
993  ret.emplace_back(Value::unpack<T>(*v));
994  } catch (const std::exception&) {}
995  }
996  return ret;
997 }
998 
999 #ifdef OPENDHT_JSONCPP
1000 uint64_t unpackId(const Json::Value& json, const std::string& key);
1001 #endif
1002 
1003 }
1004 
1005 MSGPACK_ADD_ENUM(dht::Value::Field)
Where & userType(std::string user_type)
Definition: value.h:809
Describes a value filter.
Definition: value.h:602
An index for field values.
Definition: value.h:927
Blob getToEncrypt() const
Definition: value.h:438
Value::Filter getFilter() const
Definition: value.h:821
bool checkSignature() const
Definition: value.h:342
Blob getToSign() const
Definition: value.h:428
Where & valueType(ValueType::Id type)
Definition: value.h:767
STL namespace.
Value(const Blob &userdata)
Definition: value.h:392
std::string user_type
Definition: value.h:575
Blob cypher
Definition: value.h:590
Serializable Value field selection.
Definition: value.h:686
std::shared_ptr< const crypto::PublicKey > owner
Definition: value.h:557
Select & field(Value::Field field)
Definition: value.h:700
std::set< Value::Field > getSelection() const
Definition: value.h:711
std::function< bool(InfoHash key, const std::shared_ptr< Value > &old_val, std::shared_ptr< Value > &new_val, const InfoHash &from, const SockAddr &addr)> EditPolicy
Definition: value.h:75
Where & owner(InfoHash owner_pk_hash)
Definition: value.h:781
Value(ValueType::Id t, const Blob &data, Id id=INVALID_ID)
Definition: value.h:368
Blob signature
Definition: value.h:585
std::vector< uint8_t > Blob
Definition: utils.h:114
std::function< bool(InfoHash key, std::shared_ptr< Value > &value, const InfoHash &from, const SockAddr &addr)> StorePolicy
Definition: value.h:59
ValueType::Id type
Definition: value.h:569
Describes a query destined to another peer.
Definition: value.h:863
Where & id(Value::Id id)
Definition: value.h:753
Query(std::string q_str)
Definition: value.h:882
Serializable dht::Value filter.
Definition: value.h:739
Value(const msgpack::object &o)
Definition: value.h:407
Where & seq(uint16_t seq_no)
Definition: value.h:795
OPENDHT_PUBLIC Blob unpackBlob(msgpack::object &o)
void sign(const crypto::PrivateKey &key)
Definition: value.h:331
Value encrypt(const crypto::PrivateKey &from, const crypto::PublicKey &to)
Definition: value.h:353
Definition: callbacks.h:34
Blob sign(const Blob &) const