29using namespace std::literals;
31static constexpr auto VALUE_KEY_ID(
"id");
32static const std::string VALUE_KEY_DAT(
"dat");
33static const std::string VALUE_KEY_PRIO(
"p");
34static const std::string VALUE_KEY_PUSHTYPE(
"pt");
35static const std::string VALUE_KEY_SIGNATURE(
"sig");
37static const std::string VALUE_KEY_SEQ(
"seq");
38static const std::string VALUE_KEY_DATA(
"data");
39static const std::string VALUE_KEY_OWNER(
"owner");
40static const std::string VALUE_KEY_TYPE(
"type");
41static const std::string VALUE_KEY_TO(
"to");
42static const std::string VALUE_KEY_BODY(
"body");
43static const std::string VALUE_KEY_USERTYPE(
"utype");
59 = std::function<bool(InfoHash key, std::shared_ptr<Value>& value,
const InfoHash& from,
const SockAddr& addr)>;
75using EditPolicy = std::function<bool(InfoHash key,
76 const std::shared_ptr<Value>& old_val,
77 std::shared_ptr<Value>& new_val,
81static constexpr const size_t MAX_VALUE_SIZE {1024 * 64};
82static constexpr const duration DEFAULT_VALUE_EXPIRATION {std::chrono::minutes(10)};
88 OPENDHT_PUBLIC
static bool DEFAULT_STORE_POLICY(InfoHash,
89 const std::shared_ptr<Value>& v,
92 static inline bool DEFAULT_EDIT_POLICY(
93 InfoHash,
const std::shared_ptr<Value>&, std::shared_ptr<Value>&,
const InfoHash&,
const SockAddr&)
100 ValueType(Id
id, std::string name, duration e = DEFAULT_VALUE_EXPIRATION)
114 virtual ~ValueType() {}
116 bool operator==(
const ValueType& o) {
return id == o.id; }
119 OPENDHT_PUBLIC
static const ValueType USER_DATA;
123 duration expiration {DEFAULT_VALUE_EXPIRATION};
131 void registerType(
const ValueType& type) { types[type.id] = type; }
132 const ValueType& getType(ValueType::Id type_id)
const
134 const auto& t_it = types.find(type_id);
135 return (t_it == types.end()) ? ValueType::USER_DATA : t_it->second;
139 std::map<ValueType::Id, ValueType> types {};
151struct OPENDHT_PUBLIC Value
153 enum class Field :
int {
165 static const constexpr Id INVALID_ID {0};
167 class Filter :
public std::function<bool(const Value&)>
172 template<
typename Functor>
174 : std::function<bool(
const Value&)>::function(f)
177 inline Filter chain(Filter&& f2)
180 return chain(std::move(f1), std::move(f2));
182 inline Filter chainOr(Filter&& f2)
185 return chainOr(std::move(f1), std::move(f2));
187 static inline Filter chain(Filter&& f1, Filter&& f2)
190 return std::move(f2);
192 return std::move(f1);
193 return [f1 = std::move(f1), f2 = std::move(f2)](
const Value& v) {
194 return f1(v) and f2(v);
197 static inline Filter chain(
const Filter& f1,
const Filter& f2)
203 return [f1, f2](
const Value& v) {
204 return f1(v) and f2(v);
207 static inline Filter chainAll(std::vector<Filter>&& set)
211 return [set = std::move(set)](
const Value& v) {
212 for (
const auto& f : set)
218 static inline Filter chain(std::initializer_list<Filter> l)
220 return chainAll(std::vector<Filter>(l.begin(), l.end()));
222 static inline Filter chainOr(Filter&& f1, Filter&& f2)
224 if (not f1 or not f2)
226 return [f1 = std::move(f1), f2 = std::move(f2)](
const Value& v) {
227 return f1(v) or f2(v);
230 static inline Filter notFilter(Filter&& f)
233 return [](
const Value&) {
236 return [f = std::move(f)](
const Value& v) {
240 std::vector<Sp<Value>> filter(
const std::vector<Sp<Value>>& values)
244 std::vector<Sp<Value>> ret;
245 for (
const auto& v : values)
254 static inline Filter AllFilter() {
return {}; }
256 static inline Filter TypeFilter(
const ValueType& t)
258 return [tid = t.id](
const Value& v) {
259 return v.type == tid;
262 static inline Filter TypeFilter(
const ValueType::Id& tid)
264 return [tid](
const Value& v) {
265 return v.type == tid;
269 static inline Filter IdFilter(
const Id
id)
271 return [id](
const Value& v) {
276 static inline Filter RecipientFilter(
const InfoHash& r)
278 return [r](
const Value& v) {
279 return v.recipient == r;
283 static inline Filter OwnerFilter(
const crypto::PublicKey& pk) {
return OwnerFilter(pk.getId()); }
285 static inline Filter OwnerFilter(
const InfoHash& pkh)
287 return [pkh](
const Value& v) {
288 return v.owner and v.owner->getId() == pkh;
292 static inline Filter SeqNumFilter(uint16_t seq_no)
294 return [seq_no](
const Value& v) {
295 return v.seq == seq_no;
299 static inline Filter UserTypeFilter(std::string ut)
301 return [ut = std::move(ut)](
const Value& v) {
302 return v.user_type == ut;
306 class SerializableBase
309 SerializableBase() {}
310 virtual ~SerializableBase() {};
311 virtual const ValueType& getType()
const = 0;
312 virtual void unpackValue(
const Value& v) = 0;
313 virtual Value packValue()
const = 0;
316 template<
typename Derived,
typename Base = SerializableBase>
322 virtual const ValueType& getType()
const {
return Derived::TYPE; }
324 virtual void unpackValue(
const Value& v)
326 auto msg = msgpack::unpack((
const char*) v.data.data(), v.data.size());
327 msg.get().convert(*
static_cast<Derived*
>(
this));
330 virtual Value packValue()
const {
return Value {getType(),
static_cast<const Derived&
>(*this)}; }
333 template<typename T, typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>
::type* =
nullptr>
334 static Value pack(
const T& obj)
336 return obj.packValue();
339 template<typename T, typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* =
nullptr>
340 static Value pack(
const T& obj)
342 return {ValueType::USER_DATA.id, packMsg<T>(obj)};
345 template<typename T, typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* =
nullptr>
346 static T unpack(
const Value& v)
353 template<typename T, typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* =
nullptr>
354 static T unpack(
const Value& v)
356 return unpackMsg<T>(v.data);
362 return unpack<T>(*
this);
365 inline bool isEncrypted()
const {
return not cypher.empty(); }
366 inline bool isSigned()
const {
return owner and not signature.empty(); }
381 inline std::shared_ptr<crypto::PublicKey> getOwner()
const {
return owner; }
395 Value(ValueType::Id t,
const Blob& data, Id
id = INVALID_ID)
400 Value(ValueType::Id t,
Blob&& data, Id
id = INVALID_ID)
403 , data(std::move(data))
405 Value(ValueType::Id t,
const uint8_t* dat_ptr,
size_t dat_len, Id
id = INVALID_ID)
408 , data(dat_ptr, dat_ptr + dat_len)
411#ifdef OPENDHT_JSONCPP
416 Value(
const Json::Value& json);
419 template<
typename Type>
420 Value(ValueType::Id t,
const Type& d, Id
id = INVALID_ID)
426 template<
typename Type>
427 Value(
const ValueType& t,
const Type& d, Id
id = INVALID_ID)
434 Value(
const Blob& userdata)
438 : data(std::move(userdata))
440 Value(
const uint8_t* dat_ptr,
size_t dat_len)
441 : data(dat_ptr, dat_ptr + dat_len)
444 Value(Value&& o) noexcept
446 , owner(std::move(o.owner))
447 , recipient(o.recipient)
449 , data(std::move(o.data))
450 , user_type(std::move(o.user_type))
452 , signature(std::move(o.signature))
453 , cypher(std::move(o.cypher))
454 , priority(o.priority)
455 , pushType(std::move(o.pushType))
458 template<
typename Type>
459 Value(
const Type& vs)
460 : Value(pack<Type>(vs))
466 Value(
const msgpack::object& o) { msgpack_unpack(o); }
478 inline bool operator==(
const Value& o)
const {
return id == o.id and contentEquals(o); }
479 inline bool operator!=(
const Value& o)
const {
return !(*
this == o); }
481 inline void setRecipient(
const InfoHash& r) { recipient = r; }
483 inline void setCypher(Blob&& c) { cypher = std::move(c); }
490 msgpack::sbuffer buffer;
491 msgpack::packer<msgpack::sbuffer> pk(&buffer);
492 msgpack_pack_to_sign(pk);
493 return {buffer.data(), buffer.data() + buffer.size()};
501 msgpack::sbuffer buffer;
502 msgpack::packer<msgpack::sbuffer> pk(&buffer);
503 msgpack_pack_to_encrypt(pk);
504 return {buffer.data(), buffer.data() + buffer.size()};
508 OPENDHT_PUBLIC
friend std::ostream&
operator<<(std::ostream& s,
const Value& v);
510 inline std::string toString()
const
512 std::ostringstream ss;
517#ifdef OPENDHT_JSONCPP
526 Json::Value toJson()
const;
532 template<
typename Packer>
533 void msgpack_pack_to_sign(Packer& pk)
const
538 pk.pack(VALUE_KEY_SEQ);
540 pk.pack(VALUE_KEY_OWNER);
541 owner->msgpack_pack(pk);
543 pk.pack(VALUE_KEY_TO);
547 pk.pack(VALUE_KEY_TYPE);
549 pk.pack(VALUE_KEY_DATA);
550 pk.pack_bin(data.size());
551 pk.pack_bin_body((
const char*) data.data(), data.size());
552 if (not user_type.empty()) {
553 pk.pack(VALUE_KEY_USERTYPE);
558 template<
typename Packer>
559 void msgpack_pack_to_encrypt(Packer& pk)
const
562 pk.pack_bin(cypher.size());
563 pk.pack_bin_body((
const char*) cypher.data(), cypher.size());
565 pk.pack_map(isSigned() ? 2 : 1);
566 pk.pack(VALUE_KEY_BODY);
567 msgpack_pack_to_sign(pk);
569 pk.pack(VALUE_KEY_SIGNATURE);
570 pk.pack_bin(signature.size());
571 pk.pack_bin_body((
const char*) signature.data(), signature.size());
576 template<
typename Packer>
577 void msgpack_pack(Packer& pk)
const
579 pk.pack_map(2 + (priority ? 1 : 0) + (!pushType.empty() ? 1 : 0));
580 pk.pack(VALUE_KEY_ID);
582 pk.pack(VALUE_KEY_DAT);
583 msgpack_pack_to_encrypt(pk);
585 pk.pack(VALUE_KEY_PRIO);
588 if (!pushType.empty()) {
589 pk.pack(VALUE_KEY_PUSHTYPE);
594 template<
typename Packer>
595 void msgpack_pack_fields(
const std::set<Value::Field>& fields, Packer& pk)
const
597 for (
const auto& field : fields)
599 case Value::Field::Id:
600 pk.pack(
static_cast<uint64_t
>(
id));
602 case Value::Field::ValueType:
603 pk.pack(
static_cast<uint64_t
>(type));
605 case Value::Field::OwnerPk:
607 owner->msgpack_pack(pk);
609 InfoHash().msgpack_pack(pk);
611 case Value::Field::SeqNum:
612 pk.pack(
static_cast<uint64_t
>(seq));
614 case Value::Field::UserType:
622 void msgpack_unpack(
const msgpack::object& o);
623 void msgpack_unpack_body(
const msgpack::object& o);
624 Blob getPacked()
const
626 msgpack::sbuffer buffer;
627 msgpack::packer<msgpack::sbuffer> pk(&buffer);
629 return {buffer.data(), buffer.data() + buffer.size()};
632 void msgpack_unpack_fields(
const std::set<Value::Field>& fields,
const msgpack::object& o,
unsigned offset);
639 std::shared_ptr<crypto::PublicKey>
owner {};
651 ValueType::Id
type {ValueType::USER_DATA.id};
688 inline bool isSignatureChecked()
const {
return signatureChecked; }
689 inline bool isDecrypted()
const {
return decrypted; }
690 bool checkSignature();
691 Sp<Value> decrypt(
const crypto::PrivateKey& key);
695 bool signatureChecked {
false};
696 bool signatureValid {
false};
697 bool decrypted {
false};
698 Sp<Value> decryptedValue {};
701using ValuesExport = std::pair<InfoHash, Blob>;
710struct OPENDHT_PUBLIC FieldValue
713 FieldValue(Value::Field f, uint64_t int_value)
715 , intValue(int_value)
717 FieldValue(Value::Field f, InfoHash hash_value)
719 , hashValue(hash_value)
721 FieldValue(Value::Field f,
Blob blob_value)
723 , blobValue(std::move(blob_value))
726 bool operator==(
const FieldValue& fd)
const;
729 Value::Field getField()
const {
return field; }
730 uint64_t getInt()
const {
return intValue; }
731 InfoHash getHash()
const {
return hashValue; }
732 Blob getBlob()
const {
return blobValue; }
734 template<
typename Packer>
735 void msgpack_pack(Packer& p)
const
739 p.pack(
static_cast<uint8_t
>(field));
743 case Value::Field::Id:
744 case Value::Field::ValueType:
747 case Value::Field::OwnerPk:
750 case Value::Field::UserType:
751 p.pack_bin(blobValue.size());
752 p.pack_bin_body((
const char*) blobValue.data(), blobValue.size());
755 throw msgpack::type_error();
759 void msgpack_unpack(
const msgpack::object& msg)
764 if (
auto f = findMapValue(msg,
"f"sv))
765 field = (Value::Field) f->as<
unsigned>();
767 throw msgpack::type_error();
769 auto v = findMapValue(msg,
"v"sv);
771 throw msgpack::type_error();
774 case Value::Field::Id:
775 case Value::Field::ValueType:
776 intValue = v->as<
decltype(intValue)>();
778 case Value::Field::OwnerPk:
779 hashValue = v->as<
decltype(hashValue)>();
781 case Value::Field::UserType:
785 throw msgpack::type_error();
792 Value::Field field {Value::Field::None};
794 uint64_t intValue {};
795 InfoHash hashValue {};
806struct OPENDHT_PUBLIC Select
809 Select(std::string_view q_str);
811 bool isSatisfiedBy(
const Select& os)
const;
822 if (std::find(fieldSelection_.begin(), fieldSelection_.end(),
field) == fieldSelection_.end())
823 fieldSelection_.emplace_back(
field);
832 std::set<Value::Field>
getSelection()
const {
return {fieldSelection_.begin(), fieldSelection_.end()}; }
834 template<
typename Packer>
835 void msgpack_pack(Packer& pk)
const
837 pk.pack(fieldSelection_);
839 void msgpack_unpack(
const msgpack::object& o) { fieldSelection_ = o.as<
decltype(fieldSelection_)>(); }
841 std::string toString()
const
843 std::ostringstream ss;
848 bool empty()
const {
return fieldSelection_.empty(); }
850 OPENDHT_PUBLIC
friend std::ostream& operator<<(std::ostream& s,
const dht::Select& q);
853 std::vector<Value::Field> fieldSelection_ {};
863struct OPENDHT_PUBLIC Where
866 Where(std::string_view q_str);
868 bool isSatisfiedBy(
const Where& where)
const;
877 Where&&
id(Value::Id
id)
880 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
881 filters_.emplace_back(std::move(fv));
882 return std::move(*
this);
894 FieldValue fv {Value::Field::ValueType, type};
895 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
896 filters_.emplace_back(std::move(fv));
897 return std::move(*
this);
907 Where&&
owner(InfoHash owner_pk_hash)
909 FieldValue fv {Value::Field::OwnerPk, owner_pk_hash};
910 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
911 filters_.emplace_back(std::move(fv));
912 return std::move(*
this);
922 Where&&
seq(uint16_t seq_no)
925 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
926 filters_.emplace_back(std::move(fv));
927 return std::move(*
this);
937 Where&&
userType(std::string_view user_type)
940 Value::Field::UserType,
Blob {user_type.begin(), user_type.end()}
942 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
943 filters_.emplace_back(std::move(fv));
944 return std::move(*
this);
954 if (filters_.empty())
956 if (filters_.size() == 1)
957 return filters_[0].getLocalFilter();
958 std::vector<Value::Filter> fset;
959 fset.reserve(filters_.size());
960 for (
const auto& f : filters_) {
961 if (
auto lf = f.getLocalFilter())
962 fset.emplace_back(std::move(lf));
964 return Value::Filter::chainAll(std::move(fset));
967 template<
typename Packer>
968 void msgpack_pack(Packer& pk)
const
972 void msgpack_unpack(
const msgpack::object& o)
975 filters_ = o.as<
decltype(filters_)>();
978 std::string toString()
const
980 std::ostringstream ss;
985 bool empty()
const {
return filters_.empty(); }
987 OPENDHT_PUBLIC
friend std::ostream& operator<<(std::ostream& s,
const dht::Where& q);
990 std::vector<FieldValue> filters_;
1001struct OPENDHT_PUBLIC Query
1003 static const std::string QUERY_PARSE_ERROR;
1005 Query(
Select s = {},
Where w = {},
bool none =
false)
1006 : select(std::move(s))
1007 , where(std::move(w))
1023 Query(std::string_view q_str)
1025 auto pos_W = q_str.find(
"WHERE");
1026 auto pos_w = q_str.find(
"where");
1027 auto pos = std::min(pos_W != std::string_view::npos ? pos_W : q_str.size(),
1028 pos_w != std::string_view::npos ? pos_w : q_str.size());
1029 select = q_str.substr(0, pos);
1030 where = q_str.substr(pos, q_str.size() - pos);
1038 template<
typename Packer>
1039 void msgpack_pack(Packer& pk)
const
1048 void msgpack_unpack(
const msgpack::object& o);
1050 std::string toString()
const
1052 std::ostringstream ss;
1057 friend std::ostream& operator<<(std::ostream& s,
const dht::Query& q)
1059 return s <<
"Query[" << q.select <<
" " << q.where <<
"]";
1074struct OPENDHT_PUBLIC FieldValueIndex
1076 FieldValueIndex() {}
1077 FieldValueIndex(
const Value& v,
const Select& s = {});
1084 bool containedIn(
const FieldValueIndex& other)
const;
1086 OPENDHT_PUBLIC
friend std::ostream& operator<<(std::ostream& os,
const FieldValueIndex& fvi);
1088 void msgpack_unpack_fields(
const std::set<Value::Field>& fields,
const msgpack::object& o,
unsigned offset);
1090 std::map<Value::Field, FieldValue> index {};
1093template<typename T, typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* =
nullptr>
1095getFilterSet(Value::Filter f)
1097 return Value::Filter::chain({Value::TypeFilter(T::TYPE), T::getFilter(), std::move(f)});
1100template<typename T, typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* =
nullptr>
1107template<typename T, typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* =
nullptr>
1111 return Value::Filter::chain({Value::TypeFilter(T::TYPE), T::getFilter()});
1114template<typename T, typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* =
nullptr>
1123unpackVector(
const std::vector<std::shared_ptr<Value>>& vals)
1126 ret.reserve(vals.size());
1127 for (
const auto& v : vals) {
1129 ret.emplace_back(Value::unpack<T>(*v));
1130 }
catch (
const std::exception&) {
1136#ifdef OPENDHT_JSONCPP
1137uint64_t unpackId(
const Json::Value& json,
const std::string& key);
1142MSGPACK_ADD_ENUM(dht::Value::Field)
std::function< bool(InfoHash key, std::shared_ptr< Value > &value, const InfoHash &from, const SockAddr &addr)> StorePolicy
OPENDHT_PUBLIC Blob unpackBlob(const msgpack::object &o)
std::vector< uint8_t > Blob
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
bool containedIn(const FieldValueIndex &other) const
Describes a value filter.
Describes a query destined to another peer.
bool isSatisfiedBy(const Query &q) const
Serializable Value field selection.
std::set< Value::Field > getSelection() const
Select & field(Value::Field field)
bool contentEquals(const Value &o) const
bool checkSignature() const
std::shared_ptr< crypto::PublicKey > owner
Value encrypt(const crypto::PrivateKey &from, const crypto::PublicKey &to)
OPENDHT_PUBLIC friend std::ostream & operator<<(std::ostream &s, const Value &v)
Blob getToEncrypt() const
void sign(const crypto::PrivateKey &key)
Serializable dht::Value filter.
Value::Filter getFilter() const
Where && userType(std::string_view user_type)
Where && seq(uint16_t seq_no)
Where && id(Value::Id id)
Where && valueType(ValueType::Id type)
Where && owner(InfoHash owner_pk_hash)