27 #include <msgpack.hpp> 40 #ifdef OPENDHT_JSONCPP 41 #include <json/json.h> 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)>;
77 static constexpr
const size_t MAX_VALUE_SIZE {1024 * 64};
83 static bool DEFAULT_EDIT_POLICY(
InfoHash,
const std::shared_ptr<Value>&, std::shared_ptr<Value>&,
const InfoHash&,
const SockAddr&) {
89 ValueType (Id
id, std::string name, duration e = std::chrono::minutes(10))
90 : id(
id), name(name), expiration(e) {}
93 : id(
id), name(name), expiration(e), storePolicy(sp), editPolicy(ep) {}
107 duration expiration {60 * 10};
114 void registerType(
const ValueType& type) {
115 types[type.id] = type;
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;
122 std::map<ValueType::Id, ValueType> types {};
125 struct CryptoValueCache;
138 enum class Field : int {
150 static const constexpr Id INVALID_ID {0};
152 class Filter :
public std::function<bool(const Value&)> {
156 template<
typename Functor>
157 Filter(Functor f) : std::function<bool(const Value&)>::function(f) {}
161 return chain(std::move(f1), std::move(f2));
165 return chainOr(std::move(f1), std::move(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);
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)
181 }, std::placeholders::_1, std::move(
set));
183 static Filter chain(std::initializer_list<Filter> l) {
184 return chainAll(std::vector<Filter>(l.begin(), l.end()));
187 if (not f1 or not f2)
return AllFilter();
188 return [f1,f2](
const Value& v) {
189 return f1(v) or f2(v);
192 std::vector<Sp<Value>> filter(
const std::vector<Sp<Value>>& values) {
195 std::vector<Sp<Value>> ret;
196 for (
const auto& v : values)
205 static const Filter AllFilter() {
209 static Filter TypeFilter(
const ValueType& t) {
210 const auto tid = t.id;
211 return [tid](
const Value& v) {
212 return v.type == tid;
215 static Filter TypeFilter(
const ValueType::Id& tid) {
216 return [tid](
const Value& v) {
217 return v.type == tid;
221 static Filter IdFilter(
const Id
id) {
222 return [id](
const Value& v) {
227 static Filter RecipientFilter(
const InfoHash& r) {
228 return [r](
const Value& v) {
229 return v.recipient == r;
233 static Filter OwnerFilter(
const crypto::PublicKey& pk) {
234 return OwnerFilter(pk.getId());
237 static Filter OwnerFilter(
const InfoHash& pkh) {
238 return [pkh](
const Value& v) {
239 return v.owner and v.owner->getId() == pkh;
243 static Filter SeqNumFilter(uint16_t seq_no) {
244 return [seq_no](
const Value& v) {
245 return v.seq == seq_no;
249 static Filter UserTypeFilter(
const std::string& ut) {
250 return [ut](
const Value& v) {
251 return v.user_type == ut;
260 virtual const ValueType& getType()
const = 0;
261 virtual void unpackValue(
const Value& v) = 0;
262 virtual Value packValue()
const = 0;
265 template <
typename Derived,
typename Base=SerializableBase>
271 virtual const ValueType& getType()
const {
272 return Derived::TYPE;
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));
280 virtual Value packValue()
const {
281 return Value {getType(),
static_cast<const Derived&
>(*this)};
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)
289 return obj.packValue();
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)
296 return {ValueType::USER_DATA.id, packMsg<T>(obj)};
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)
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)
312 return unpackMsg<T>(v.data);
315 template <
typename T>
318 return unpack<T>(*this);
321 bool isEncrypted()
const {
322 return not cypher.empty();
324 bool isSigned()
const {
325 return owner and not signature.empty();
336 owner = std::make_shared<const crypto::PublicKey>(key.getPublicKey());
337 signature = key.
sign(getToSign());
345 return isSigned() and owner->checkSignature(getToSign(), signature);
348 std::shared_ptr<const crypto::PublicKey> getOwner()
const {
358 setRecipient(to.
getId());
361 nv.setCypher(to.encrypt(getToEncrypt()));
367 Value (Id
id) : id(id) {}
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) {}
377 #ifdef OPENDHT_JSONCPP 382 Value(Json::Value& json);
385 template <
typename Type>
386 Value(ValueType::Id t,
const Type& d, Id
id = INVALID_ID)
387 : id(id), type(t), data(packMsg(d)) {}
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)) {}
396 Value(
const uint8_t* dat_ptr,
size_t dat_len) : data(dat_ptr, dat_ptr+dat_len) {}
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)) {}
402 template <
typename Type>
403 Value(
const Type& vs)
404 : Value(pack<Type>(vs)) {}
413 inline bool operator== (
const Value& o) {
415 (isEncrypted() ? cypher == o.
cypher :
419 void setRecipient(
const InfoHash& r) {
423 void setCypher(
Blob&& c) {
424 cypher = std::move(c);
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()};
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()};
448 OPENDHT_PUBLIC
friend std::ostream& operator<< (std::ostream& s,
const Value& v);
450 std::string toString()
const {
451 std::stringstream ss;
456 #ifdef OPENDHT_JSONCPP 465 Json::Value toJson()
const;
471 template <
typename Packer>
472 void msgpack_pack_to_sign(Packer& pk)
const 474 bool has_owner = owner && *owner;
475 pk.pack_map((user_type.empty()?0:1) + (has_owner?(recipient ? 5 : 4):2));
477 pk.pack(std::string(
"seq")); pk.pack(seq);
478 pk.pack(std::string(
"owner")); owner->msgpack_pack(pk);
480 pk.pack(std::string(
"to")); pk.pack(recipient);
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);
491 template <
typename Packer>
492 void msgpack_pack_to_encrypt(Packer& pk)
const 495 pk.pack_bin(cypher.size());
496 pk.pack_bin_body((
const char*)cypher.data(), cypher.size());
498 pk.pack_map(isSigned() ? 2 : 1);
499 pk.pack(std::string(
"body")); msgpack_pack_to_sign(pk);
501 pk.pack(std::string(
"sig")); pk.pack_bin(signature.size());
502 pk.pack_bin_body((
const char*)signature.data(), signature.size());
507 template <
typename Packer>
508 void msgpack_pack(Packer& pk)
const 511 pk.pack(std::string(
"id")); pk.pack(
id);
512 pk.pack(std::string(
"dat")); msgpack_pack_to_encrypt(pk);
515 template <
typename Packer>
516 void msgpack_pack_fields(
const std::set<Value::Field>& fields, Packer& pk)
const 518 for (
const auto& field : fields)
520 case Value::Field::Id:
521 pk.pack(static_cast<uint64_t>(
id));
523 case Value::Field::ValueType:
524 pk.pack(static_cast<uint64_t>(type));
526 case Value::Field::OwnerPk:
528 owner->msgpack_pack(pk);
530 InfoHash().msgpack_pack(pk);
532 case Value::Field::SeqNum:
533 pk.pack(static_cast<uint64_t>(seq));
535 case Value::Field::UserType:
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);
549 return {buffer.data(), buffer.data()+buffer.size()};
552 void msgpack_unpack_fields(
const std::set<Value::Field>& fields,
const msgpack::object& o,
unsigned offset);
559 std::shared_ptr<const crypto::PublicKey> owner {};
571 ValueType::Id type {ValueType::USER_DATA.id};
577 std::string user_type {};
597 bool signatureChecked {
false};
598 bool signatureValid {
false};
599 bool decrypted {
false};
600 Sp<Value> decryptedValue {};
603 using ValuesExport = std::pair<InfoHash, Blob>;
615 FieldValue(Value::Field f, uint64_t int_value) : field(f), intValue(int_value) {}
617 FieldValue(Value::Field f,
Blob blob_value) : field(f), blobValue(blob_value) {}
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; }
627 template <
typename Packer>
628 void msgpack_pack(Packer& p)
const {
630 p.pack(std::string(
"f")); p.pack(static_cast<uint8_t>(field));
632 p.pack(std::string(
"v"));
634 case Value::Field::Id:
635 case Value::Field::ValueType:
638 case Value::Field::OwnerPk:
641 case Value::Field::UserType:
642 p.pack_bin(blobValue.size());
643 p.pack_bin_body((
const char*)blobValue.data(), blobValue.size());
646 throw msgpack::type_error();
650 void msgpack_unpack(msgpack::object msg) {
654 if (
auto f = findMapValue(msg,
"f"))
655 field = (Value::Field)f->as<
unsigned>();
657 throw msgpack::type_error();
659 auto v = findMapValue(msg,
"v");
661 throw msgpack::type_error();
664 case Value::Field::Id:
665 case Value::Field::ValueType:
666 intValue = v->as<decltype(intValue)>();
668 case Value::Field::OwnerPk:
669 hashValue = v->as<decltype(hashValue)>();
671 case Value::Field::UserType:
675 throw msgpack::type_error();
682 Value::Field field {Value::Field::None};
684 uint64_t intValue {};
699 Select(
const std::string& q_str);
701 bool isSatisfiedBy(
const Select& os)
const;
711 if (std::find(fieldSelection_.begin(), fieldSelection_.end(), field) == fieldSelection_.end())
712 fieldSelection_.emplace_back(field);
722 return {fieldSelection_.begin(), fieldSelection_.end()};
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_)>();
731 std::string toString()
const {
732 std::stringstream ss;
737 OPENDHT_PUBLIC
friend std::ostream& operator<<(std::ostream& s,
const dht::Select& q);
739 std::vector<Value::Field> fieldSelection_ {};
752 Where(
const std::string& q_str);
754 bool isSatisfiedBy(
const Where& where)
const;
765 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
766 filters_.emplace_back(std::move(fv));
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));
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));
807 if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
808 filters_.emplace_back(std::move(fv));
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));
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));
839 return Value::Filter::chainAll(std::move(fset));
842 template <
typename Packer>
843 void msgpack_pack(Packer& pk)
const { pk.pack(filters_); }
844 void msgpack_unpack(
const msgpack::object& o) {
846 filters_ = o.as<decltype(filters_)>();
849 std::string toString()
const {
850 std::stringstream ss;
856 return filters_.empty();
859 OPENDHT_PUBLIC
friend std::ostream& operator<<(std::ostream& s,
const dht::Where& q);
862 std::vector<FieldValue> filters_;
875 static const std::string QUERY_PARSE_ERROR;
877 Query(
Select s = {},
Where w = {},
bool none =
false) : select(s), where(w), none(none) { };
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);
904 bool isSatisfiedBy(
const Query& q)
const;
906 template <
typename Packer>
907 void msgpack_pack(Packer& pk)
const {
909 pk.pack(std::string(
"s")); pk.pack(select);
910 pk.pack(std::string(
"w")); pk.pack(where);
913 void msgpack_unpack(
const msgpack::object& o);
915 std::string toString()
const {
916 std::stringstream ss;
921 OPENDHT_PUBLIC
friend std::ostream& operator<<(std::ostream& s,
const dht::Query& q) {
922 return s <<
"Query[" << q.select <<
" " << q.where <<
"]";
948 OPENDHT_PUBLIC
friend std::ostream& operator<<(std::ostream& os,
const FieldValueIndex& fvi);
950 void msgpack_unpack_fields(
const std::set<Value::Field>& fields,
951 const msgpack::object& o,
954 std::map<Value::Field, FieldValue> index {};
957 template <
typename T,
958 typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* =
nullptr>
962 return Value::Filter::chain({
963 Value::TypeFilter(T::TYPE),
969 template <
typename T,
970 typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* =
nullptr>
972 getFilterSet(Value::Filter f)
977 template <
typename T,
978 typename std::enable_if<std::is_base_of<Value::SerializableBase, T>::value, T>::type* =
nullptr>
982 return Value::Filter::chain({
983 Value::TypeFilter(T::TYPE),
988 template <
typename T,
989 typename std::enable_if<!std::is_base_of<Value::SerializableBase, T>::value, T>::type* =
nullptr>
993 return Value::AllFilter();
998 unpackVector(
const std::vector<std::shared_ptr<Value>>& vals) {
1000 ret.reserve(vals.size());
1001 for (
const auto& v : vals) {
1003 ret.emplace_back(Value::unpack<T>(*v));
1004 }
catch (
const std::exception&) {}
1009 #ifdef OPENDHT_JSONCPP 1010 uint64_t unpackId(
const Json::Value& json,
const std::string& key);
1015 MSGPACK_ADD_ENUM(dht::Value::Field)
Blob getToEncrypt() const
Where & userType(std::string user_type)
Describes a value filter.
An index for field values.
bool checkSignature() const
Value::Filter getFilter() const
Where & valueType(ValueType::Id type)
Value(const Blob &userdata)
Serializable Value field selection.
std::shared_ptr< const crypto::PublicKey > owner
Select & field(Value::Field field)
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
Where & owner(InfoHash owner_pk_hash)
Value(ValueType::Id t, const Blob &data, Id id=INVALID_ID)
std::vector< uint8_t > Blob
std::function< bool(InfoHash key, std::shared_ptr< Value > &value, const InfoHash &from, const SockAddr &addr)> StorePolicy
Describes a query destined to another peer.
Serializable dht::Value filter.
Value(const msgpack::object &o)
Blob sign(const Blob &) const
std::set< Value::Field > getSelection() const
Where & seq(uint16_t seq_no)
OPENDHT_PUBLIC Blob unpackBlob(msgpack::object &o)
void sign(const crypto::PrivateKey &key)
Value encrypt(const crypto::PrivateKey &from, const crypto::PublicKey &to)