46using namespace std::literals;
48static constexpr auto VALUE_KEY_ID(
"id");
49static const std::string VALUE_KEY_DAT(
"dat");
50static const std::string VALUE_KEY_PRIO(
"p");
51static const std::string VALUE_KEY_SIGNATURE(
"sig");
53static const std::string VALUE_KEY_SEQ(
"seq");
54static const std::string VALUE_KEY_DATA(
"data");
55static const std::string VALUE_KEY_OWNER(
"owner");
56static const std::string VALUE_KEY_TYPE(
"type");
57static const std::string VALUE_KEY_TO(
"to");
58static const std::string VALUE_KEY_BODY(
"body");
59static const std::string VALUE_KEY_USERTYPE(
"utype");
92static constexpr const size_t MAX_VALUE_SIZE {1024 * 64};
98 static bool DEFAULT_EDIT_POLICY(
InfoHash,
const std::shared_ptr<Value>&, std::shared_ptr<Value>&,
const InfoHash&,
const SockAddr&) {
104 ValueType (Id
id, std::string name, duration e = std::chrono::minutes(10))
105 : id(
id), name(name), expiration(e) {}
108 : id(
id), name(name), expiration(e), storePolicy(sp), editPolicy(ep) {}
122 duration expiration {std::chrono::minutes(10)};
129 void registerType(
const ValueType& type) {
130 types[type.id] = type;
132 const ValueType& getType(ValueType::Id type_id)
const {
133 const auto& t_it = types.find(type_id);
134 return (t_it == types.end()) ? ValueType::USER_DATA : t_it->second;
137 std::map<ValueType::Id, ValueType> types {};
140struct CryptoValueCache;
153 enum class Field :
int {
165 static const constexpr Id INVALID_ID {0};
167 class Filter :
public std::function<bool(const Value&)> {
171 template<
typename Functor>
172 Filter(Functor f) : std::function<bool(
const Value&)>::function(f) {}
176 return chain(std::move(f1), std::move(f2));
180 return chainOr(std::move(f1), std::move(f2));
183 if (not f1)
return std::move(f2);
184 if (not f2)
return std::move(f1);
185 return [f1 = std::move(f1), f2 = std::move(f2)](
const Value& v) {
186 return f1(v) and f2(v);
190 if (not f1)
return f2;
191 if (not f2)
return f1;
192 return [f1,f2](
const Value& v) {
193 return f1(v) and f2(v);
196 static Filter chainAll(std::vector<Filter>&& set) {
197 if (set.empty())
return {};
198 return [set = std::move(set)](
const Value& v) {
199 for (
const auto& f : set)
205 static Filter chain(std::initializer_list<Filter> l) {
206 return chainAll(std::vector<Filter>(l.begin(), l.end()));
209 if (not f1 or not f2)
return {};
210 return [f1=std::move(f1),f2=std::move(f2)](
const Value& v) {
211 return f1(v) or f2(v);
215 if (not f)
return [](
const Value&) {
return false; };
216 return [f](
const Value& v) {
return not f(v); };
218 std::vector<Sp<Value>> filter(
const std::vector<Sp<Value>>& values) {
221 std::vector<Sp<Value>> ret;
222 for (
const auto& v : values)
231 static const Filter AllFilter() {
235 static Filter TypeFilter(
const ValueType& t) {
236 return [tid = t.id](
const Value& v) {
237 return v.type == tid;
240 static Filter TypeFilter(
const ValueType::Id& tid) {
241 return [tid](
const Value& v) {
242 return v.type == tid;
246 static Filter IdFilter(
const Id
id) {
247 return [id](
const Value& v) {
252 static Filter RecipientFilter(
const InfoHash& r) {
253 return [r](
const Value& v) {
254 return v.recipient == r;
258 static Filter OwnerFilter(
const crypto::PublicKey& pk) {
259 return OwnerFilter(pk.getId());
262 static Filter OwnerFilter(
const InfoHash& pkh) {
263 return [pkh](
const Value& v) {
264 return v.owner and v.owner->getId() == pkh;
268 static Filter SeqNumFilter(uint16_t seq_no) {
269 return [seq_no](
const Value& v) {
270 return v.seq == seq_no;
274 static Filter UserTypeFilter(std::string ut) {
275 return [ut = std::move(ut)](
const Value& v) {
276 return v.user_type == ut;
285 virtual const ValueType& getType()
const = 0;
286 virtual void unpackValue(
const Value& v) = 0;
287 virtual Value packValue()
const = 0;
290 template <
typename Derived,
typename Base=SerializableBase>
296 virtual const ValueType& getType()
const {
297 return Derived::TYPE;
300 virtual void unpackValue(
const Value& v) {
301 auto msg = msgpack::unpack((
const char*)v.data.data(), v.data.size());
302 msg.get().convert(*
static_cast<Derived*
>(
this));
305 virtual Value packValue()
const {
306 return Value {getType(),
static_cast<const Derived&
>(*this)};
310 template <
typename T,
311 typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* =
nullptr>
312 static Value pack(
const T& obj)
314 return obj.packValue();
317 template <
typename T,
318 typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* =
nullptr>
319 static Value pack(
const T& obj)
321 return {ValueType::USER_DATA.id, packMsg<T>(obj)};
324 template <
typename T,
325 typename std::enable_if<std::is_base_of<SerializableBase, T>::value, T>::type* =
nullptr>
326 static T unpack(
const Value& v)
333 template <
typename T,
334 typename std::enable_if<!std::is_base_of<SerializableBase, T>::value, T>::type* =
nullptr>
335 static T unpack(
const Value& v)
337 return unpackMsg<T>(v.data);
340 template <
typename T>
343 return unpack<T>(*
this);
346 bool isEncrypted()
const {
347 return not cypher.empty();
349 bool isSigned()
const {
350 return owner and not signature.empty();
361 owner = key.getSharedPublicKey();
362 signature = key.
sign(getToSign());
370 return isSigned() and owner->checkSignature(getToSign(), signature);
373 std::shared_ptr<crypto::PublicKey> getOwner()
const {
374 return std::static_pointer_cast<crypto::PublicKey>(owner);
383 setRecipient(to.
getId());
386 nv.setCypher(to.encrypt(getToEncrypt()));
392 Value (Id
id) : id(id) {}
395 Value(ValueType::Id t,
const Blob& data, Id
id = INVALID_ID)
396 : id(id), type(t), data(data) {}
397 Value(ValueType::Id t,
Blob&& data, Id
id = INVALID_ID)
398 : id(id), type(t), data(std::move(data)) {}
399 Value(ValueType::Id t,
const uint8_t* dat_ptr,
size_t dat_len, Id
id = INVALID_ID)
400 : id(id), type(t), data(dat_ptr, dat_ptr+dat_len) {}
402#ifdef OPENDHT_JSONCPP
407 Value(
const Json::Value& json);
410 template <
typename Type>
411 Value(ValueType::Id t,
const Type& d, Id
id = INVALID_ID)
412 : id(id), type(t), data(packMsg(d)) {}
414 template <
typename Type>
415 Value(
const ValueType& t,
const Type& d, Id
id = INVALID_ID)
416 : id(id), type(t.id), data(packMsg(d)) {}
420 Value(
Blob&& userdata) : data(std::move(userdata)) {}
421 Value(
const uint8_t* dat_ptr,
size_t dat_len) : data(dat_ptr, dat_ptr+dat_len) {}
423 Value(Value&& o) noexcept
424 : id(o.id), owner(std::move(o.owner)), recipient(o.recipient),
425 type(o.type), data(std::move(o.data)), user_type(std::move(o.user_type)), seq(o.seq)
426 , signature(std::move(o.signature)), cypher(std::move(o.cypher))
427 , priority(o.priority) {}
429 template <
typename Type>
430 Value(
const Type& vs)
431 : Value(pack<Type>(vs)) {}
444 return isEncrypted() ? cypher == o.
cypher :
452 inline bool operator== (
const Value& o) {
453 return id == o.id and contentEquals(o);
456 void setRecipient(
const InfoHash& r) {
460 void setCypher(Blob&& c) {
461 cypher = std::move(c);
468 msgpack::sbuffer buffer;
469 msgpack::packer<msgpack::sbuffer> pk(&buffer);
470 msgpack_pack_to_sign(pk);
471 return {buffer.data(), buffer.data()+buffer.size()};
478 msgpack::sbuffer buffer;
479 msgpack::packer<msgpack::sbuffer> pk(&buffer);
480 msgpack_pack_to_encrypt(pk);
481 return {buffer.data(), buffer.data()+buffer.size()};
485 OPENDHT_PUBLIC
friend std::ostream& operator<< (std::ostream& s,
const Value& v);
487 std::string toString()
const {
488 std::stringstream ss;
493#ifdef OPENDHT_JSONCPP
502 Json::Value toJson()
const;
508 template <
typename Packer>
509 void msgpack_pack_to_sign(Packer& pk)
const
511 bool has_owner = owner && *owner;
512 pk.pack_map((user_type.empty()?0:1) + (has_owner?(recipient ? 5 : 4):2));
514 pk.pack(VALUE_KEY_SEQ); pk.pack(seq);
515 pk.pack(VALUE_KEY_OWNER); owner->msgpack_pack(pk);
517 pk.pack(VALUE_KEY_TO); pk.pack(recipient);
520 pk.pack(VALUE_KEY_TYPE); pk.pack(type);
521 pk.pack(VALUE_KEY_DATA); pk.pack_bin(data.size());
522 pk.pack_bin_body((
const char*)data.data(), data.size());
523 if (not user_type.empty()) {
524 pk.pack(VALUE_KEY_USERTYPE); pk.pack(user_type);
528 template <
typename Packer>
529 void msgpack_pack_to_encrypt(Packer& pk)
const
532 pk.pack_bin(cypher.size());
533 pk.pack_bin_body((
const char*)cypher.data(), cypher.size());
535 pk.pack_map(isSigned() ? 2 : 1);
536 pk.pack(VALUE_KEY_BODY); msgpack_pack_to_sign(pk);
538 pk.pack(VALUE_KEY_SIGNATURE); pk.pack_bin(signature.size());
539 pk.pack_bin_body((
const char*)signature.data(), signature.size());
544 template <
typename Packer>
545 void msgpack_pack(Packer& pk)
const
547 pk.pack_map(2 + (priority?1:0));
548 pk.pack(VALUE_KEY_ID); pk.pack(
id);
549 pk.pack(VALUE_KEY_DAT); msgpack_pack_to_encrypt(pk);
551 pk.pack(VALUE_KEY_PRIO); pk.pack(priority);
555 template <
typename Packer>
556 void msgpack_pack_fields(
const std::set<Value::Field>& fields, Packer& pk)
const
558 for (
const auto& field : fields)
560 case Value::Field::Id:
561 pk.pack(
static_cast<uint64_t
>(
id));
563 case Value::Field::ValueType:
564 pk.pack(
static_cast<uint64_t
>(type));
566 case Value::Field::OwnerPk:
568 owner->msgpack_pack(pk);
570 InfoHash().msgpack_pack(pk);
572 case Value::Field::SeqNum:
573 pk.pack(
static_cast<uint64_t
>(seq));
575 case Value::Field::UserType:
583 void msgpack_unpack(
const msgpack::object& o);
584 void msgpack_unpack_body(
const msgpack::object& o);
585 Blob getPacked()
const {
586 msgpack::sbuffer buffer;
587 msgpack::packer<msgpack::sbuffer> pk(&buffer);
589 return {buffer.data(), buffer.data()+buffer.size()};
592 void msgpack_unpack_fields(
const std::set<Value::Field>& fields,
const msgpack::object& o,
unsigned offset);
599 std::shared_ptr<crypto::PublicKey> owner {};
611 ValueType::Id type {ValueType::USER_DATA.id};
617 std::string user_type {};
639 unsigned priority {0};
641 bool checkSignature();
646 bool signatureChecked {
false};
647 bool signatureValid {
false};
648 bool decrypted {
false};
649 Sp<Value> decryptedValue {};
652using ValuesExport = std::pair<InfoHash, Blob>;
664 FieldValue(Value::Field f, uint64_t int_value) : field(f), intValue(int_value) {}
666 FieldValue(Value::Field f,
Blob blob_value) : field(f), blobValue(std::move(blob_value)) {}
671 Value::Field getField()
const {
return field; }
672 uint64_t getInt()
const {
return intValue; }
673 InfoHash getHash()
const {
return hashValue; }
674 Blob getBlob()
const {
return blobValue; }
676 template <
typename Packer>
677 void msgpack_pack(Packer& p)
const {
679 p.pack(
"f"sv); p.pack(
static_cast<uint8_t
>(field));
683 case Value::Field::Id:
684 case Value::Field::ValueType:
687 case Value::Field::OwnerPk:
690 case Value::Field::UserType:
691 p.pack_bin(blobValue.size());
692 p.pack_bin_body((
const char*)blobValue.data(), blobValue.size());
695 throw msgpack::type_error();
699 void msgpack_unpack(
const msgpack::object& msg) {
703 if (
auto f = findMapValue(msg,
"f"sv))
704 field = (Value::Field)f->as<
unsigned>();
706 throw msgpack::type_error();
708 auto v = findMapValue(msg,
"v"sv);
710 throw msgpack::type_error();
713 case Value::Field::Id:
714 case Value::Field::ValueType:
715 intValue = v->as<
decltype(intValue)>();
717 case Value::Field::OwnerPk:
718 hashValue = v->as<
decltype(hashValue)>();
720 case Value::Field::UserType:
724 throw msgpack::type_error();
731 Value::Field field {Value::Field::None};
733 uint64_t intValue {};
748 Select(std::string_view q_str);
750 bool isSatisfiedBy(
const Select& os)
const;
760 if (std::find(fieldSelection_.begin(), fieldSelection_.end(), field) == fieldSelection_.end())
761 fieldSelection_.emplace_back(field);
771 return {fieldSelection_.begin(), fieldSelection_.end()};
774 template <
typename Packer>
775 void msgpack_pack(Packer& pk)
const { pk.pack(fieldSelection_); }
776 void msgpack_unpack(
const msgpack::object& o) {
777 fieldSelection_ = o.as<
decltype(fieldSelection_)>();
780 std::string toString()
const {
781 std::stringstream ss;
786 bool empty()
const {
return fieldSelection_.empty(); }
788 OPENDHT_PUBLIC
friend std::ostream& operator<<(std::ostream& s,
const dht::Select& q);
790 std::vector<Value::Field> fieldSelection_ {};
803 Where(std::string_view q_str);
805 bool isSatisfiedBy(
const Where& where)
const;
816 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
817 filters_.emplace_back(std::move(fv));
829 FieldValue fv {Value::Field::ValueType, type};
830 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
831 filters_.emplace_back(std::move(fv));
843 FieldValue fv {Value::Field::OwnerPk, owner_pk_hash};
844 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
845 filters_.emplace_back(std::move(fv));
858 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
859 filters_.emplace_back(std::move(fv));
871 FieldValue fv {Value::Field::UserType,
Blob {user_type.begin(), user_type.end()}};
872 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
873 filters_.emplace_back(std::move(fv));
883 if (filters_.empty())
return {};
884 std::vector<Value::Filter> fset;
885 fset.reserve(filters_.size());
886 for (
const auto& f : filters_) {
887 if (
auto lf = f.getLocalFilter())
888 fset.emplace_back(std::move(lf));
890 return Value::Filter::chainAll(std::move(fset));
893 template <
typename Packer>
894 void msgpack_pack(Packer& pk)
const { pk.pack(filters_); }
895 void msgpack_unpack(
const msgpack::object& o) {
897 filters_ = o.as<
decltype(filters_)>();
900 std::string toString()
const {
901 std::stringstream ss;
907 return filters_.empty();
910 OPENDHT_PUBLIC
friend std::ostream& operator<<(std::ostream& s,
const dht::Where& q);
913 std::vector<FieldValue> filters_;
926 static const std::string QUERY_PARSE_ERROR;
928 Query(
Select s = {},
Where w = {},
bool none =
false) : select(std::move(s)), where(std::move(w)), none(none) { };
944 auto pos_W = q_str.find(
"WHERE");
945 auto pos_w = q_str.find(
"where");
946 auto pos = std::min(pos_W != std::string_view::npos ? pos_W : q_str.size(),
947 pos_w != std::string_view::npos ? pos_w : q_str.size());
948 select = q_str.substr(0, pos);
949 where = q_str.substr(pos, q_str.size()-pos);
957 template <
typename Packer>
958 void msgpack_pack(Packer& pk)
const {
960 pk.pack(std::string(
"s")); pk.pack(select);
961 pk.pack(std::string(
"w")); pk.pack(where);
964 void msgpack_unpack(
const msgpack::object& o);
966 std::string toString()
const {
967 std::stringstream ss;
972 OPENDHT_PUBLIC
friend std::ostream& operator<<(std::ostream& s,
const dht::Query& q) {
973 return s <<
"Query[" << q.select <<
" " << q.where <<
"]";
999 OPENDHT_PUBLIC
friend std::ostream& operator<<(std::ostream& os,
const FieldValueIndex& fvi);
1001 void msgpack_unpack_fields(
const std::set<Value::Field>& fields,
1002 const msgpack::object& o,
1005 std::map<Value::Field, FieldValue> index {};
1008template <
typename T,
1009 typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* =
nullptr>
1011getFilterSet(Value::Filter f)
1013 return Value::Filter::chain({
1014 Value::TypeFilter(T::TYPE),
1020template <
typename T,
1021 typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* =
nullptr>
1023getFilterSet(Value::Filter f)
1028template <
typename T,
1029 typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* =
nullptr>
1033 return Value::Filter::chain({
1034 Value::TypeFilter(T::TYPE),
1039template <
typename T,
1040 typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* =
nullptr>
1049unpackVector(
const std::vector<std::shared_ptr<Value>>& vals) {
1051 ret.reserve(vals.size());
1052 for (
const auto& v : vals) {
1054 ret.emplace_back(Value::unpack<T>(*v));
1055 }
catch (
const std::exception&) {}
1060#ifdef OPENDHT_JSONCPP
1061uint64_t unpackId(
const Json::Value& json,
const std::string& key);
1066MSGPACK_ADD_ENUM(dht::Value::Field)
OPENDHT_PUBLIC Blob unpackBlob(const msgpack::object &o)
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
std::vector< uint8_t > Blob
std::function< bool(InfoHash key, std::shared_ptr< Value > &value, const InfoHash &from, const SockAddr &addr)> StorePolicy
An index for field values.
bool containedIn(const FieldValueIndex &other) const
Describes a value filter.
Describes a query destined to another peer.
Query(std::string_view q_str)
bool isSatisfiedBy(const Query &q) const
Serializable Value field selection.
std::set< Value::Field > getSelection() const
Select & field(Value::Field field)
bool checkSignature() const
std::shared_ptr< crypto::PublicKey > owner
Value(const msgpack::object &o)
Value(ValueType::Id t, const Blob &data, Id id=INVALID_ID)
Value encrypt(const crypto::PrivateKey &from, const crypto::PublicKey &to)
bool contentEquals(const Value &o)
Blob getToEncrypt() const
Value(const Blob &userdata)
void sign(const crypto::PrivateKey &key)
Serializable dht::Value filter.
Value::Filter getFilter() const
Where & seq(uint16_t seq_no)
Where & valueType(ValueType::Id type)
Where & owner(InfoHash owner_pk_hash)
Where & userType(std::string_view user_type)
Blob sign(const uint8_t *data, size_t data_len) const