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 
125 struct CryptoValueCache;
126 
136 struct OPENDHT_PUBLIC Value
137 {
138  enum class Field : int {
139  None = 0,
140  Id, /* Value::id */
141  ValueType, /* Value::type */
142  OwnerPk, /* Value::owner */
143  SeqNum, /* Value::seq */
144  UserType, /* Value::user_type */
145 
146  COUNT /* the total number of fields */
147  };
148 
149  typedef uint64_t Id;
150  static const constexpr Id INVALID_ID {0};
151 
152  class Filter : public std::function<bool(const Value&)> {
153  public:
154  Filter() {}
155 
156  template<typename Functor>
157  Filter(Functor f) : std::function<bool(const Value&)>::function(f) {}
158 
159  Filter chain(Filter&& f2) {
160  auto f1 = *this;
161  return chain(std::move(f1), std::move(f2));
162  }
163  Filter chainOr(Filter&& f2) {
164  auto f1 = *this;
165  return chainOr(std::move(f1), std::move(f2));
166  }
167  static Filter chain(Filter&& f1, Filter&& f2) {
168  if (not f1) return f2;
169  if (not f2) return f1;
170  return [f1,f2](const Value& v) {
171  return f1(v) and f2(v);
172  };
173  }
174  static Filter chainAll(std::vector<Filter>&& set) {
175  if (set.empty()) return {};
176  return std::bind([](const Value& v, std::vector<Filter>& s) {
177  for (const auto& f : s)
178  if (f and not f(v))
179  return false;
180  return true;
181  }, std::placeholders::_1, std::move(set));
182  }
183  static Filter chain(std::initializer_list<Filter> l) {
184  return chainAll(std::vector<Filter>(l.begin(), l.end()));
185  }
186  static Filter chainOr(Filter&& f1, Filter&& f2) {
187  if (not f1 or not f2) return AllFilter();
188  return [f1,f2](const Value& v) {
189  return f1(v) or f2(v);
190  };
191  }
192  std::vector<Sp<Value>> filter(const std::vector<Sp<Value>>& values) {
193  if (not (*this))
194  return values;
195  std::vector<Sp<Value>> ret;
196  for (const auto& v : values)
197  if ((*this)(v))
198  ret.emplace_back(v);
199  return ret;
200  }
201  };
202 
203  /* Sneaky functions disguised in classes */
204 
205  static const Filter AllFilter() {
206  return {};
207  }
208 
209  static Filter TypeFilter(const ValueType& t) {
210  const auto tid = t.id;
211  return [tid](const Value& v) {
212  return v.type == tid;
213  };
214  }
215  static Filter TypeFilter(const ValueType::Id& tid) {
216  return [tid](const Value& v) {
217  return v.type == tid;
218  };
219  }
220 
221  static Filter IdFilter(const Id id) {
222  return [id](const Value& v) {
223  return v.id == id;
224  };
225  }
226 
227  static Filter RecipientFilter(const InfoHash& r) {
228  return [r](const Value& v) {
229  return v.recipient == r;
230  };
231  }
232 
233  static Filter OwnerFilter(const crypto::PublicKey& pk) {
234  return OwnerFilter(pk.getId());
235  }
236 
237  static Filter OwnerFilter(const InfoHash& pkh) {
238  return [pkh](const Value& v) {
239  return v.owner and v.owner->getId() == pkh;
240  };
241  }
242 
243  static Filter SeqNumFilter(uint16_t seq_no) {
244  return [seq_no](const Value& v) {
245  return v.seq == seq_no;
246  };
247  }
248 
249  static Filter UserTypeFilter(const std::string& ut) {
250  return [ut](const Value& v) {
251  return v.user_type == ut;
252  };
253  }
254 
256  {
257  public:
258  SerializableBase() {}
259  virtual ~SerializableBase() {};
260  virtual const ValueType& getType() const = 0;
261  virtual void unpackValue(const Value& v) = 0;
262  virtual Value packValue() const = 0;
263  };
264 
265  template <typename Derived, typename Base=SerializableBase>
266  class Serializable : public Base
267  {
268  public:
269  using Base::Base;
270 
271  virtual const ValueType& getType() const {
272  return Derived::TYPE;
273  }
274 
275  virtual void unpackValue(const Value& v) {
276  auto msg = msgpack::unpack((const char*)v.data.data(), v.data.size());
277  msg.get().convert(*static_cast<Derived*>(this));
278  }
279 
280  virtual Value packValue() const {
281  return Value {getType(), static_cast<const Derived&>(*this)};
282  }
283  };
284 
285  template <typename T,
286  typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
287  static Value pack(const T& obj)
288  {
289  return obj.packValue();
290  }
291 
292  template <typename T,
293  typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
294  static Value pack(const T& obj)
295  {
296  return {ValueType::USER_DATA.id, packMsg<T>(obj)};
297  }
298 
299  template <typename T,
300  typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
301  static T unpack(const Value& v)
302  {
303  T msg;
304  msg.unpackValue(v);
305  return msg;
306  }
307 
308  template <typename T,
309  typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* = nullptr>
310  static T unpack(const Value& v)
311  {
312  return unpackMsg<T>(v.data);
313  }
314 
315  template <typename T>
316  T unpack()
317  {
318  return unpack<T>(*this);
319  }
320 
321  bool isEncrypted() const {
322  return not cypher.empty();
323  }
324  bool isSigned() const {
325  return owner and not signature.empty();
326  }
327 
333  void sign(const crypto::PrivateKey& key) {
334  if (isEncrypted())
335  throw DhtException("Can't sign encrypted data.");
336  owner = std::make_shared<const crypto::PublicKey>(key.getPublicKey());
337  signature = key.sign(getToSign());
338  }
339 
344  bool checkSignature() const {
345  return isSigned() and owner->checkSignature(getToSign(), signature);
346  }
347 
348  std::shared_ptr<const crypto::PublicKey> getOwner() const {
349  return std::static_pointer_cast<const crypto::PublicKey>(owner);
350  }
351 
356  if (isEncrypted())
357  throw DhtException("Data is already encrypted.");
358  setRecipient(to.getId());
359  sign(from);
360  Value nv {id};
361  nv.setCypher(to.encrypt(getToEncrypt()));
362  return nv;
363  }
364 
365  Value() {}
366 
367  Value (Id id) : id(id) {}
368 
370  Value(ValueType::Id t, const Blob& data, Id id = INVALID_ID)
371  : id(id), type(t), data(data) {}
372  Value(ValueType::Id t, Blob&& data, Id id = INVALID_ID)
373  : id(id), type(t), data(std::move(data)) {}
374  Value(ValueType::Id t, const uint8_t* dat_ptr, size_t dat_len, Id id = INVALID_ID)
375  : id(id), type(t), data(dat_ptr, dat_ptr+dat_len) {}
376 
377 #ifdef OPENDHT_JSONCPP
378 
382  Value(Json::Value& json);
383 #endif
384 
385  template <typename Type>
386  Value(ValueType::Id t, const Type& d, Id id = INVALID_ID)
387  : id(id), type(t), data(packMsg(d)) {}
388 
389  template <typename Type>
390  Value(const ValueType& t, const Type& d, Id id = INVALID_ID)
391  : id(id), type(t.id), data(packMsg(d)) {}
392 
394  Value(const Blob& userdata) : data(userdata) {}
395  Value(Blob&& userdata) : data(std::move(userdata)) {}
396  Value(const uint8_t* dat_ptr, size_t dat_len) : data(dat_ptr, dat_ptr+dat_len) {}
397 
398  Value(Value&& o) noexcept
399  : id(o.id), owner(std::move(o.owner)), recipient(o.recipient),
400  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)) {}
401 
402  template <typename Type>
403  Value(const Type& vs)
404  : Value(pack<Type>(vs)) {}
405 
409  Value(const msgpack::object& o) {
410  msgpack_unpack(o);
411  }
412 
413  inline bool operator== (const Value& o) {
414  return id == o.id &&
415  (isEncrypted() ? cypher == o.cypher :
416  ((owner == o.owner || *owner == *o.owner) && type == o.type && data == o.data && user_type == o.user_type && signature == o.signature));
417  }
418 
419  void setRecipient(const InfoHash& r) {
420  recipient = r;
421  }
422 
423  void setCypher(Blob&& c) {
424  cypher = std::move(c);
425  }
426 
430  Blob getToSign() const {
431  msgpack::sbuffer buffer;
432  msgpack::packer<msgpack::sbuffer> pk(&buffer);
433  msgpack_pack_to_sign(pk);
434  return {buffer.data(), buffer.data()+buffer.size()};
435  }
436 
440  Blob getToEncrypt() const {
441  msgpack::sbuffer buffer;
442  msgpack::packer<msgpack::sbuffer> pk(&buffer);
443  msgpack_pack_to_encrypt(pk);
444  return {buffer.data(), buffer.data()+buffer.size()};
445  }
446 
448  OPENDHT_PUBLIC friend std::ostream& operator<< (std::ostream& s, const Value& v);
449 
450  std::string toString() const {
451  std::stringstream ss;
452  ss << *this;
453  return ss.str();
454  }
455 
456 #ifdef OPENDHT_JSONCPP
457 
465  Json::Value toJson() const;
466 #endif
467 
469  size_t size() const;
470 
471  template <typename Packer>
472  void msgpack_pack_to_sign(Packer& pk) const
473  {
474  bool has_owner = owner && *owner;
475  pk.pack_map((user_type.empty()?0:1) + (has_owner?(recipient ? 5 : 4):2));
476  if (has_owner) { // isSigned
477  pk.pack(std::string("seq")); pk.pack(seq);
478  pk.pack(std::string("owner")); owner->msgpack_pack(pk);
479  if (recipient) {
480  pk.pack(std::string("to")); pk.pack(recipient);
481  }
482  }
483  pk.pack(std::string("type")); pk.pack(type);
484  pk.pack(std::string("data")); pk.pack_bin(data.size());
485  pk.pack_bin_body((const char*)data.data(), data.size());
486  if (not user_type.empty()) {
487  pk.pack(std::string("utype")); pk.pack(user_type);
488  }
489  }
490 
491  template <typename Packer>
492  void msgpack_pack_to_encrypt(Packer& pk) const
493  {
494  if (isEncrypted()) {
495  pk.pack_bin(cypher.size());
496  pk.pack_bin_body((const char*)cypher.data(), cypher.size());
497  } else {
498  pk.pack_map(isSigned() ? 2 : 1);
499  pk.pack(std::string("body")); msgpack_pack_to_sign(pk);
500  if (isSigned()) {
501  pk.pack(std::string("sig")); pk.pack_bin(signature.size());
502  pk.pack_bin_body((const char*)signature.data(), signature.size());
503  }
504  }
505  }
506 
507  template <typename Packer>
508  void msgpack_pack(Packer& pk) const
509  {
510  pk.pack_map(2);
511  pk.pack(std::string("id")); pk.pack(id);
512  pk.pack(std::string("dat")); msgpack_pack_to_encrypt(pk);
513  }
514 
515  template <typename Packer>
516  void msgpack_pack_fields(const std::set<Value::Field>& fields, Packer& pk) const
517  {
518  for (const auto& field : fields)
519  switch (field) {
520  case Value::Field::Id:
521  pk.pack(static_cast<uint64_t>(id));
522  break;
523  case Value::Field::ValueType:
524  pk.pack(static_cast<uint64_t>(type));
525  break;
526  case Value::Field::OwnerPk:
527  if (owner)
528  owner->msgpack_pack(pk);
529  else
530  InfoHash().msgpack_pack(pk);
531  break;
532  case Value::Field::SeqNum:
533  pk.pack(static_cast<uint64_t>(seq));
534  break;
535  case Value::Field::UserType:
536  pk.pack(user_type);
537  break;
538  default:
539  break;
540  }
541  }
542 
543  void msgpack_unpack(msgpack::object o);
544  void msgpack_unpack_body(const msgpack::object& o);
545  Blob getPacked() const {
546  msgpack::sbuffer buffer;
547  msgpack::packer<msgpack::sbuffer> pk(&buffer);
548  pk.pack(*this);
549  return {buffer.data(), buffer.data()+buffer.size()};
550  }
551 
552  void msgpack_unpack_fields(const std::set<Value::Field>& fields, const msgpack::object& o, unsigned offset);
553 
554  Id id {INVALID_ID};
555 
559  std::shared_ptr<const crypto::PublicKey> owner {};
560 
566  InfoHash recipient {};
567 
571  ValueType::Id type {ValueType::USER_DATA.id};
572  Blob data {};
573 
577  std::string user_type {};
578 
582  uint16_t seq {0};
583 
587  Blob signature {};
588 
592  Blob cypher {};
593 
594 private:
595  friend class SecureDht;
596  /* Cache for crypto ops */
597  bool signatureChecked {false};
598  bool signatureValid {false};
599  bool decrypted {false};
600  Sp<Value> decryptedValue {};
601 };
602 
603 using ValuesExport = std::pair<InfoHash, Blob>;
604 
612 struct OPENDHT_PUBLIC FieldValue
613 {
614  FieldValue() {}
615  FieldValue(Value::Field f, uint64_t int_value) : field(f), intValue(int_value) {}
616  FieldValue(Value::Field f, InfoHash hash_value) : field(f), hashValue(hash_value) {}
617  FieldValue(Value::Field f, Blob blob_value) : field(f), blobValue(blob_value) {}
618 
619  bool operator==(const FieldValue& fd) const;
620 
621  // accessors
622  Value::Field getField() const { return field; }
623  uint64_t getInt() const { return intValue; }
624  InfoHash getHash() const { return hashValue; }
625  Blob getBlob() const { return blobValue; }
626 
627  template <typename Packer>
628  void msgpack_pack(Packer& p) const {
629  p.pack_map(2);
630  p.pack(std::string("f")); p.pack(static_cast<uint8_t>(field));
631 
632  p.pack(std::string("v"));
633  switch (field) {
634  case Value::Field::Id:
635  case Value::Field::ValueType:
636  p.pack(intValue);
637  break;
638  case Value::Field::OwnerPk:
639  p.pack(hashValue);
640  break;
641  case Value::Field::UserType:
642  p.pack_bin(blobValue.size());
643  p.pack_bin_body((const char*)blobValue.data(), blobValue.size());
644  break;
645  default:
646  throw msgpack::type_error();
647  }
648  }
649 
650  void msgpack_unpack(msgpack::object msg) {
651  hashValue = {};
652  blobValue.clear();
653 
654  if (auto f = findMapValue(msg, "f"))
655  field = (Value::Field)f->as<unsigned>();
656  else
657  throw msgpack::type_error();
658 
659  auto v = findMapValue(msg, "v");
660  if (not v)
661  throw msgpack::type_error();
662  else
663  switch (field) {
664  case Value::Field::Id:
665  case Value::Field::ValueType:
666  intValue = v->as<decltype(intValue)>();
667  break;
668  case Value::Field::OwnerPk:
669  hashValue = v->as<decltype(hashValue)>();
670  break;
671  case Value::Field::UserType:
672  blobValue = unpackBlob(*v);
673  break;
674  default:
675  throw msgpack::type_error();
676  }
677  }
678 
679  Value::Filter getLocalFilter() const;
680 
681 private:
682  Value::Field field {Value::Field::None};
683  // three possible value types
684  uint64_t intValue {};
685  InfoHash hashValue {};
686  Blob blobValue {};
687 };
688 
696 struct OPENDHT_PUBLIC Select
697 {
698  Select() { }
699  Select(const std::string& q_str);
700 
701  bool isSatisfiedBy(const Select& os) const;
702 
710  Select& field(Value::Field field) {
711  if (std::find(fieldSelection_.begin(), fieldSelection_.end(), field) == fieldSelection_.end())
712  fieldSelection_.emplace_back(field);
713  return *this;
714  }
715 
721  std::set<Value::Field> getSelection() const {
722  return {fieldSelection_.begin(), fieldSelection_.end()};
723  }
724 
725  template <typename Packer>
726  void msgpack_pack(Packer& pk) const { pk.pack(fieldSelection_); }
727  void msgpack_unpack(const msgpack::object& o) {
728  fieldSelection_ = o.as<decltype(fieldSelection_)>();
729  }
730 
731  std::string toString() const {
732  std::stringstream ss;
733  ss << *this;
734  return ss.str();
735  }
736 
737  OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Select& q);
738 private:
739  std::vector<Value::Field> fieldSelection_ {};
740 };
741 
749 struct OPENDHT_PUBLIC Where
750 {
751  Where() { }
752  Where(const std::string& q_str);
753 
754  bool isSatisfiedBy(const Where& where) const;
755 
763  Where& id(Value::Id id) {
764  FieldValue fv {Value::Field::Id, id};
765  if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
766  filters_.emplace_back(std::move(fv));
767  return *this;
768  }
769 
777  Where& valueType(ValueType::Id type) {
778  FieldValue fv {Value::Field::ValueType, type};
779  if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
780  filters_.emplace_back(std::move(fv));
781  return *this;
782  }
783 
791  Where& owner(InfoHash owner_pk_hash) {
792  FieldValue fv {Value::Field::OwnerPk, owner_pk_hash};
793  if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
794  filters_.emplace_back(std::move(fv));
795  return *this;
796  }
797 
805  Where& seq(uint16_t seq_no) {
806  FieldValue fv {Value::Field::SeqNum, seq_no};
807  if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
808  filters_.emplace_back(std::move(fv));
809  return *this;
810  }
811 
819  Where& userType(std::string user_type) {
820  FieldValue fv {Value::Field::UserType, Blob {user_type.begin(), user_type.end()}};
821  if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
822  filters_.emplace_back(std::move(fv));
823  return *this;
824  }
825 
832  if (filters_.empty()) return {};
833  std::vector<Value::Filter> fset;
834  fset.reserve(filters_.size());
835  for (const auto& f : filters_) {
836  if (auto lf = f.getLocalFilter())
837  fset.emplace_back(std::move(lf));
838  }
839  return Value::Filter::chainAll(std::move(fset));
840  }
841 
842  template <typename Packer>
843  void msgpack_pack(Packer& pk) const { pk.pack(filters_); }
844  void msgpack_unpack(const msgpack::object& o) {
845  filters_.clear();
846  filters_ = o.as<decltype(filters_)>();
847  }
848 
849  std::string toString() const {
850  std::stringstream ss;
851  ss << *this;
852  return ss.str();
853  }
854 
855  bool empty() const {
856  return filters_.empty();
857  }
858 
859  OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Where& q);
860 
861 private:
862  std::vector<FieldValue> filters_;
863 };
864 
873 struct OPENDHT_PUBLIC Query
874 {
875  static const std::string QUERY_PARSE_ERROR;
876 
877  Query(Select s = {}, Where w = {}, bool none = false) : select(s), where(w), none(none) { };
878 
892  Query(std::string q_str) {
893  auto pos_W = q_str.find("WHERE");
894  auto pos_w = q_str.find("where");
895  auto pos = std::min(pos_W != std::string::npos ? pos_W : q_str.size(),
896  pos_w != std::string::npos ? pos_w : q_str.size());
897  select = q_str.substr(0, pos);
898  where = q_str.substr(pos, q_str.size()-pos);
899  }
900 
904  bool isSatisfiedBy(const Query& q) const;
905 
906  template <typename Packer>
907  void msgpack_pack(Packer& pk) const {
908  pk.pack_map(2);
909  pk.pack(std::string("s")); pk.pack(select); /* packing field selectors */
910  pk.pack(std::string("w")); pk.pack(where); /* packing filters */
911  }
912 
913  void msgpack_unpack(const msgpack::object& o);
914 
915  std::string toString() const {
916  std::stringstream ss;
917  ss << *this;
918  return ss.str();
919  }
920 
921  OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Query& q) {
922  return s << "Query[" << q.select << " " << q.where << "]";
923  }
924 
925  Select select {};
926  Where where {};
927  bool none {false}; /* When true, any query satisfies this. */
928 };
929 
937 struct OPENDHT_PUBLIC FieldValueIndex {
938  FieldValueIndex() {}
939  FieldValueIndex(const Value& v, Select s = {});
946  bool containedIn(const FieldValueIndex& other) const;
947 
948  OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& os, const FieldValueIndex& fvi);
949 
950  void msgpack_unpack_fields(const std::set<Value::Field>& fields,
951  const msgpack::object& o,
952  unsigned offset);
953 
954  std::map<Value::Field, FieldValue> index {};
955 };
956 
957 template <typename T,
958  typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
960 getFilterSet(Value::Filter f)
961 {
962  return Value::Filter::chain({
963  Value::TypeFilter(T::TYPE),
964  T::getFilter(),
965  f
966  });
967 }
968 
969 template <typename T,
970  typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
971 Value::Filter
972 getFilterSet(Value::Filter f)
973 {
974  return f;
975 }
976 
977 template <typename T,
978  typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
979 Value::Filter
980 getFilterSet()
981 {
982  return Value::Filter::chain({
983  Value::TypeFilter(T::TYPE),
984  T::getFilter()
985  });
986 }
987 
988 template <typename T,
989  typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* = nullptr>
990 Value::Filter
991 getFilterSet()
992 {
993  return Value::AllFilter();
994 }
995 
996 template <class T>
997 std::vector<T>
998 unpackVector(const std::vector<std::shared_ptr<Value>>& vals) {
999  std::vector<T> ret;
1000  ret.reserve(vals.size());
1001  for (const auto& v : vals) {
1002  try {
1003  ret.emplace_back(Value::unpack<T>(*v));
1004  } catch (const std::exception&) {}
1005  }
1006  return ret;
1007 }
1008 
1009 #ifdef OPENDHT_JSONCPP
1010 uint64_t unpackId(const Json::Value& json, const std::string& key);
1011 #endif
1012 
1013 }
1014 
1015 MSGPACK_ADD_ENUM(dht::Value::Field)
Blob getToEncrypt() const
Definition: value.h:440
Where & userType(std::string user_type)
Definition: value.h:819
Describes a value filter.
Definition: value.h:612
An index for field values.
Definition: value.h:937
bool checkSignature() const
Definition: value.h:344
Value::Filter getFilter() const
Definition: value.h:831
Where & valueType(ValueType::Id type)
Definition: value.h:777
STL namespace.
Value(const Blob &userdata)
Definition: value.h:394
std::string user_type
Definition: value.h:577
Blob cypher
Definition: value.h:592
Serializable Value field selection.
Definition: value.h:696
std::shared_ptr< const crypto::PublicKey > owner
Definition: value.h:559
Select & field(Value::Field field)
Definition: value.h:710
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:791
Value(ValueType::Id t, const Blob &data, Id id=INVALID_ID)
Definition: value.h:370
Blob signature
Definition: value.h:587
std::vector< uint8_t > Blob
Definition: utils.h:114
Blob getToSign() const
Definition: value.h:430
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:571
InfoHash getId() const
Describes a query destined to another peer.
Definition: value.h:873
Where & id(Value::Id id)
Definition: value.h:763
Query(std::string q_str)
Definition: value.h:892
Serializable dht::Value filter.
Definition: value.h:749
Value(const msgpack::object &o)
Definition: value.h:409
Blob sign(const Blob &) const
std::set< Value::Field > getSelection() const
Definition: value.h:721
Where & seq(uint16_t seq_no)
Definition: value.h:805
OPENDHT_PUBLIC Blob unpackBlob(msgpack::object &o)
void sign(const crypto::PrivateKey &key)
Definition: value.h:333
Value encrypt(const crypto::PrivateKey &from, const crypto::PublicKey &to)
Definition: value.h:355
Definition: callbacks.h:34